Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 176bce77 authored by Cody Kesting's avatar Cody Kesting
Browse files

Include Bundle values with ConnectivityDiagnostics calls.

ConnectivityDiagnostics allows PersistableBundles to be passed from
NetworkMonitor to ConnectivityDiagnosticsCallbacks that are registered
with the System in ConnectivityService. This change populates the
bundles passed from NetworkMonitor with values relating to
ConnectivityDiagnosticsManager#ConnectivityReport and
ConnectivityDiagnosticsManager#DataStallReport using keys defined in
those classes. The keys used for the bundles are defined in
ConstantsShim.

Bug: 147249364
Test: compiles
Test: atest NetworkStackTests
Change-Id: Id007ab38a20c6a107c9528e3e861dafa191797c3
Merged-In: Id007ab38a20c6a107c9528e3e861dafa191797c3
parent 782cbfa3
Loading
Loading
Loading
Loading
+8 −1
Original line number Diff line number Diff line
@@ -20,7 +20,14 @@ package com.android.networkstack.apishim.api29;
 * Utility class for defining and importing constants from the Android platform.
 */
public class ConstantsShim {
    // Constants defined in android.net.ConnectivityDiagnosticsManager.DataStallReport.
    // Constants defined in android.net.ConnectivityDiagnosticsManager.
    public static final int DETECTION_METHOD_DNS_EVENTS = 1;
    public static final int DETECTION_METHOD_TCP_METRICS = 2;
    public static final String KEY_DNS_CONSECUTIVE_TIMEOUTS = "dnsConsecutiveTimeouts";
    public static final String KEY_NETWORK_PROBES_ATTEMPTED_BITMASK = "networkProbesAttemped";
    public static final String KEY_NETWORK_PROBES_SUCCEEDED_BITMASK = "networkProbesSucceeded";
    public static final String KEY_NETWORK_VALIDATION_RESULT = "networkValidationResult";
    public static final String KEY_TCP_METRICS_COLLECTION_PERIOD_MILLIS =
            "tcpMetricsCollectionPeriodMillis";
    public static final String KEY_TCP_PACKET_FAIL_RATE = "tcpPacketFailRate";
}
+12 −0
Original line number Diff line number Diff line
@@ -16,6 +16,7 @@

package com.android.networkstack.apishim;

import static android.net.ConnectivityDiagnosticsManager.ConnectivityReport;
import static android.net.ConnectivityDiagnosticsManager.DataStallReport;

/**
@@ -26,4 +27,15 @@ public class ConstantsShim extends com.android.networkstack.apishim.api29.Consta
            DataStallReport.DETECTION_METHOD_DNS_EVENTS;
    public static final int DETECTION_METHOD_TCP_METRICS =
            DataStallReport.DETECTION_METHOD_TCP_METRICS;
    public static final String KEY_DNS_CONSECUTIVE_TIMEOUTS =
            DataStallReport.KEY_DNS_CONSECUTIVE_TIMEOUTS;
    public static final String KEY_NETWORK_PROBES_ATTEMPTED_BITMASK =
            ConnectivityReport.KEY_NETWORK_PROBES_ATTEMPTED_BITMASK;
    public static final String KEY_NETWORK_PROBES_SUCCEEDED_BITMASK =
            ConnectivityReport.KEY_NETWORK_PROBES_SUCCEEDED_BITMASK;
    public static final String KEY_NETWORK_VALIDATION_RESULT =
            ConnectivityReport.KEY_NETWORK_VALIDATION_RESULT;
    public static final String KEY_TCP_METRICS_COLLECTION_PERIOD_MILLIS =
            DataStallReport.KEY_TCP_METRICS_COLLECTION_PERIOD_MILLIS;
    public static final String KEY_TCP_PACKET_FAIL_RATE = DataStallReport.KEY_TCP_PACKET_FAIL_RATE;
}
+28 −7
Original line number Diff line number Diff line
@@ -70,6 +70,12 @@ import static android.provider.DeviceConfig.NAMESPACE_CONNECTIVITY;

import static com.android.networkstack.apishim.ConstantsShim.DETECTION_METHOD_DNS_EVENTS;
import static com.android.networkstack.apishim.ConstantsShim.DETECTION_METHOD_TCP_METRICS;
import static com.android.networkstack.apishim.ConstantsShim.KEY_DNS_CONSECUTIVE_TIMEOUTS;
import static com.android.networkstack.apishim.ConstantsShim.KEY_NETWORK_PROBES_ATTEMPTED_BITMASK;
import static com.android.networkstack.apishim.ConstantsShim.KEY_NETWORK_PROBES_SUCCEEDED_BITMASK;
import static com.android.networkstack.apishim.ConstantsShim.KEY_NETWORK_VALIDATION_RESULT;
import static com.android.networkstack.apishim.ConstantsShim.KEY_TCP_METRICS_COLLECTION_PERIOD_MILLIS;
import static com.android.networkstack.apishim.ConstantsShim.KEY_TCP_PACKET_FAIL_RATE;
import static com.android.networkstack.util.DnsUtils.PRIVATE_DNS_PROBE_HOST_SUFFIX;
import static com.android.networkstack.util.DnsUtils.TYPE_ADDRCONFIG;

@@ -584,9 +590,15 @@ public class NetworkMonitor extends StateMachine {
        return NetworkMonitorUtils.isPrivateDnsValidationRequired(mNetworkCapabilities);
    }

    private void notifyNetworkTested(int result, @Nullable String redirectUrl) {
    private void notifyNetworkTested(
            int result, @Nullable String redirectUrl, PersistableBundle extras) {
        try {
            if (mCallbackVersion <= 5) {
                mCallback.notifyNetworkTested(result, redirectUrl);
            } else {
                mCallback.notifyNetworkTestedWithExtras(
                        result, redirectUrl, SystemClock.elapsedRealtime(), extras);
            }
        } catch (RemoteException e) {
            Log.e(TAG, "Error sending network test result", e);
        }
@@ -2288,8 +2300,10 @@ public class NetworkMonitor extends StateMachine {
            } else if (tst.isDataStallSuspected()) {
                result = true;

                // TODO(b/147249364): add metrics to PersistableBundle once keys are defined
                notifyDataStallSuspected(DETECTION_METHOD_TCP_METRICS, PersistableBundle.EMPTY);
                final PersistableBundle extras = new PersistableBundle();
                extras.putInt(KEY_TCP_PACKET_FAIL_RATE, tst.getLatestPacketFailPercentage());
                extras.putInt(KEY_TCP_METRICS_COLLECTION_PERIOD_MILLIS, getTcpPollingInterval());
                notifyDataStallSuspected(DETECTION_METHOD_TCP_METRICS, extras);
            }
            if (DBG || VDBG_STALL) {
                msg.add("tcp packets received=" + tst.getLatestReceivedCount())
@@ -2308,8 +2322,10 @@ public class NetworkMonitor extends StateMachine {
                result = true;
                logNetworkEvent(NetworkEvent.NETWORK_CONSECUTIVE_DNS_TIMEOUT_FOUND);

                // TODO(b/147249364): add metrics to PersistableBundle once keys are defined
                notifyDataStallSuspected(DETECTION_METHOD_DNS_EVENTS, PersistableBundle.EMPTY);
                final PersistableBundle extras = new PersistableBundle();
                extras.putInt(KEY_DNS_CONSECUTIVE_TIMEOUTS,
                        mDnsStallDetector.getConsecutiveTimeoutCount());
                notifyDataStallSuspected(DETECTION_METHOD_DNS_EVENTS, extras);
            }
            if (DBG || VDBG_STALL) {
                msg.add("consecutive dns timeout count=" + dsd.getConsecutiveTimeoutCount());
@@ -2387,7 +2403,12 @@ public class NetworkMonitor extends StateMachine {
        protected void reportEvaluationResult(int result, @Nullable String redirectUrl) {
            mEvaluationResult = result;
            mRedirectUrl = redirectUrl;
            notifyNetworkTested(getNetworkTestResult(), mRedirectUrl);
            final PersistableBundle extras = new PersistableBundle();

            extras.putInt(KEY_NETWORK_VALIDATION_RESULT, result);
            extras.putInt(KEY_NETWORK_PROBES_SUCCEEDED_BITMASK, mProbeResults);
            extras.putInt(KEY_NETWORK_PROBES_ATTEMPTED_BITMASK, mProbeCompleted);
            notifyNetworkTested(getNetworkTestResult(), mRedirectUrl, extras);
        }

        protected int getNetworkTestResult() {
+103 −42
Original line number Diff line number Diff line
@@ -40,6 +40,12 @@ import static android.net.util.NetworkStackUtils.CAPTIVE_PORTAL_USE_HTTPS;

import static com.android.networkstack.apishim.ConstantsShim.DETECTION_METHOD_DNS_EVENTS;
import static com.android.networkstack.apishim.ConstantsShim.DETECTION_METHOD_TCP_METRICS;
import static com.android.networkstack.apishim.ConstantsShim.KEY_DNS_CONSECUTIVE_TIMEOUTS;
import static com.android.networkstack.apishim.ConstantsShim.KEY_NETWORK_PROBES_ATTEMPTED_BITMASK;
import static com.android.networkstack.apishim.ConstantsShim.KEY_NETWORK_PROBES_SUCCEEDED_BITMASK;
import static com.android.networkstack.apishim.ConstantsShim.KEY_NETWORK_VALIDATION_RESULT;
import static com.android.networkstack.apishim.ConstantsShim.KEY_TCP_METRICS_COLLECTION_PERIOD_MILLIS;
import static com.android.networkstack.apishim.ConstantsShim.KEY_TCP_PACKET_FAIL_RATE;
import static com.android.networkstack.util.DnsUtils.PRIVATE_DNS_PROBE_HOST_SUFFIX;

import static junit.framework.Assert.assertEquals;
@@ -51,6 +57,7 @@ import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import static org.mockito.ArgumentMatchers.anyLong;
import static org.mockito.ArgumentMatchers.argThat;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.any;
import static org.mockito.Mockito.anyInt;
@@ -121,6 +128,7 @@ import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.ArgumentCaptor;
import org.mockito.ArgumentMatcher;
import org.mockito.Captor;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
@@ -456,10 +464,13 @@ public class NetworkMonitorTest {
    }

    private void resetCallbacks() {
        resetCallbacks(6);
    }

    private void resetCallbacks(int interfaceVersion) {
        reset(mCallbacks);
        // TODO: make this a parameterized test.
        try {
            when(mCallbacks.getInterfaceVersion()).thenReturn(3);
            when(mCallbacks.getInterfaceVersion()).thenReturn(interfaceVersion);
        } catch (RemoteException e) {
            // Can't happen as mCallbacks is a mock
            fail("Error mocking getInterfaceVersion" + e);
@@ -781,7 +792,7 @@ public class NetworkMonitorTest {
        makeDnsTimeoutEvent(wrappedMonitor, DEFAULT_DNS_TIMEOUT_THRESHOLD);
        assertTrue(wrappedMonitor.isDataStall());
        verify(mCallbacks).notifyDataStallSuspected(anyLong(), eq(DETECTION_METHOD_DNS_EVENTS),
                any(PersistableBundle.class));
                argThat(getDataStallDnsBundleMatcher()));
    }

    @Test
@@ -794,7 +805,7 @@ public class NetworkMonitorTest {
        makeDnsTimeoutEvent(wrappedMonitor, DEFAULT_DNS_TIMEOUT_THRESHOLD);
        assertTrue(wrappedMonitor.isDataStall());
        verify(mCallbacks).notifyDataStallSuspected(anyLong(), eq(DETECTION_METHOD_DNS_EVENTS),
                any(PersistableBundle.class));
                argThat(getDataStallDnsBundleMatcher()));
    }

    @Test
@@ -811,7 +822,7 @@ public class NetworkMonitorTest {
        makeDnsTimeoutEvent(wrappedMonitor, 3);
        assertTrue(wrappedMonitor.isDataStall());
        verify(mCallbacks).notifyDataStallSuspected(anyLong(), eq(DETECTION_METHOD_DNS_EVENTS),
                any(PersistableBundle.class));
                argThat(getDataStallDnsBundleMatcher()));

        // Set the value to larger than the default dns log size.
        setConsecutiveDnsTimeoutThreshold(51);
@@ -823,7 +834,7 @@ public class NetworkMonitorTest {
        makeDnsTimeoutEvent(wrappedMonitor, 1);
        assertTrue(wrappedMonitor.isDataStall());
        verify(mCallbacks, times(2)).notifyDataStallSuspected(anyLong(),
                eq(DETECTION_METHOD_DNS_EVENTS), any(PersistableBundle.class));
                eq(DETECTION_METHOD_DNS_EVENTS), argThat(getDataStallDnsBundleMatcher()));
    }

    @Test
@@ -849,7 +860,7 @@ public class NetworkMonitorTest {
        wrappedMonitor.setLastProbeTime(SystemClock.elapsedRealtime() - 1000);
        assertTrue(wrappedMonitor.isDataStall());
        verify(mCallbacks).notifyDataStallSuspected(anyLong(), eq(DETECTION_METHOD_DNS_EVENTS),
                any(PersistableBundle.class));
                argThat(getDataStallDnsBundleMatcher()));

        // Test dns events happened before valid dns time threshold.
        setValidDataStallDnsTimeThreshold(0);
@@ -884,7 +895,7 @@ public class NetworkMonitorTest {
        HandlerUtilsKt.waitForIdle(wrappedMonitor.getHandler(), HANDLER_TIMEOUT_MS);
        assertTrue(wrappedMonitor.isDataStall());
        verify(mCallbacks).notifyDataStallSuspected(anyLong(), eq(DETECTION_METHOD_TCP_METRICS),
                any(PersistableBundle.class));
                argThat(getDataStallTcpBundleMatcher()));
    }

    @Test
@@ -950,8 +961,9 @@ public class NetworkMonitorTest {
        resetCallbacks();
        nm.notifyCaptivePortalAppFinished(APP_RETURN_DISMISSED);
        verify(mCallbacks, timeout(HANDLER_TIMEOUT_MS).atLeastOnce())
                .notifyNetworkTested(eq(NETWORK_VALIDATION_PROBE_DNS | NETWORK_VALIDATION_PROBE_HTTP
                        | NETWORK_VALIDATION_RESULT_VALID), any());
                .notifyNetworkTestedWithExtras(eq(NETWORK_VALIDATION_PROBE_DNS
                        | NETWORK_VALIDATION_PROBE_HTTP | NETWORK_VALIDATION_RESULT_VALID), any(),
                        anyLong(), argThat(getNotifyNetworkTestedBundleMatcher()));
        assertEquals(0, mRegisteredReceivers.size());
    }

@@ -967,8 +979,9 @@ public class NetworkMonitorTest {
                new InetAddress[0]));
        wnm.notifyNetworkConnected(TEST_LINK_PROPERTIES, NOT_METERED_CAPABILITIES);
        verify(mCallbacks, timeout(HANDLER_TIMEOUT_MS).times(1))
                .notifyNetworkTested(eq(VALIDATION_RESULT_VALID | NETWORK_VALIDATION_PROBE_PRIVDNS),
                        eq(null));
                .notifyNetworkTestedWithExtras(eq(VALIDATION_RESULT_VALID
                        | NETWORK_VALIDATION_PROBE_PRIVDNS), eq(null), anyLong(),
                        argThat(getNotifyNetworkTestedBundleMatcher()));
        verify(mCallbacks, timeout(HANDLER_TIMEOUT_MS).times(1)).notifyProbeStatusChanged(
                eq(VALIDATION_RESULT_PRIVDNS_VALID), eq(VALIDATION_RESULT_PRIVDNS_VALID));

@@ -978,8 +991,9 @@ public class NetworkMonitorTest {
        wnm.notifyPrivateDnsSettingsChanged(new PrivateDnsConfig("dns4.google",
                new InetAddress[0]));
        verify(mCallbacks, timeout(HANDLER_TIMEOUT_MS).times(1))
                .notifyNetworkTested(eq(VALIDATION_RESULT_VALID | NETWORK_VALIDATION_PROBE_PRIVDNS),
                        eq(null));
                .notifyNetworkTestedWithExtras(eq(VALIDATION_RESULT_VALID
                        | NETWORK_VALIDATION_PROBE_PRIVDNS), eq(null), anyLong(),
                        argThat(getNotifyNetworkTestedBundleMatcher()));
        // NetworkMonitor will check if the probes has changed or not, if the probes has not
        // changed, the callback won't be fired.
        verify(mCallbacks, never()).notifyProbeStatusChanged(
@@ -991,8 +1005,9 @@ public class NetworkMonitorTest {
        mFakeDns.setAnswer("dns.google", new String[]{"192.0.2.3"}, TYPE_A);
        wnm.notifyPrivateDnsSettingsChanged(new PrivateDnsConfig("dns.google", new InetAddress[0]));
        verify(mCallbacks, timeout(HANDLER_TIMEOUT_MS).times(1))
                .notifyNetworkTested(eq(VALIDATION_RESULT_VALID | NETWORK_VALIDATION_PROBE_PRIVDNS),
                        eq(null));
                .notifyNetworkTestedWithExtras(eq(VALIDATION_RESULT_VALID
                        | NETWORK_VALIDATION_PROBE_PRIVDNS), eq(null), anyLong(),
                        argThat(getNotifyNetworkTestedBundleMatcher()));
        verify(mCallbacks, never()).notifyProbeStatusChanged(
                eq(VALIDATION_RESULT_PRIVDNS_VALID), eq(VALIDATION_RESULT_PRIVDNS_VALID));
    }
@@ -1006,8 +1021,9 @@ public class NetworkMonitorTest {
        WrappedNetworkMonitor wnm = makeNotMeteredNetworkMonitor();
        wnm.notifyPrivateDnsSettingsChanged(new PrivateDnsConfig("dns.google", new InetAddress[0]));
        wnm.notifyNetworkConnected(TEST_LINK_PROPERTIES, NOT_METERED_CAPABILITIES);
        verify(mCallbacks, timeout(HANDLER_TIMEOUT_MS).times(1)).notifyNetworkTested(
                eq(NETWORK_VALIDATION_PROBE_DNS | NETWORK_VALIDATION_PROBE_HTTPS), eq(null));
        verify(mCallbacks, timeout(HANDLER_TIMEOUT_MS).times(1)).notifyNetworkTestedWithExtras(
                eq(NETWORK_VALIDATION_PROBE_DNS | NETWORK_VALIDATION_PROBE_HTTPS), eq(null),
                anyLong(), argThat(getNotifyNetworkTestedBundleMatcher()));
        verify(mCallbacks, timeout(HANDLER_TIMEOUT_MS).times(1)).notifyProbeStatusChanged(
                eq(VALIDATION_RESULT_PRIVDNS_VALID), eq(NETWORK_VALIDATION_PROBE_DNS
                | NETWORK_VALIDATION_PROBE_HTTPS));
@@ -1020,8 +1036,9 @@ public class NetworkMonitorTest {
        HandlerUtilsKt.waitForIdle(wnm.getHandler(), HANDLER_TIMEOUT_MS);
        assertEquals(wnm.getEvaluationState().getProbeCompletedResult(), 0);
        verify(mCallbacks, timeout(HANDLER_TIMEOUT_MS).times(1))
                .notifyNetworkTested(eq(VALIDATION_RESULT_VALID | NETWORK_VALIDATION_PROBE_PRIVDNS),
                        eq(null));
                .notifyNetworkTestedWithExtras(eq(VALIDATION_RESULT_VALID
                        | NETWORK_VALIDATION_PROBE_PRIVDNS), eq(null), anyLong(),
                        argThat(getNotifyNetworkTestedBundleMatcher()));
        verify(mCallbacks, timeout(HANDLER_TIMEOUT_MS).times(1)).notifyProbeStatusChanged(
                eq(VALIDATION_RESULT_PRIVDNS_VALID), eq(VALIDATION_RESULT_PRIVDNS_VALID));
    }
@@ -1035,8 +1052,9 @@ public class NetworkMonitorTest {
        WrappedNetworkMonitor wnm = makeNotMeteredNetworkMonitor();
        wnm.notifyPrivateDnsSettingsChanged(new PrivateDnsConfig("dns.google", new InetAddress[0]));
        wnm.notifyNetworkConnected(TEST_LINK_PROPERTIES, NOT_METERED_CAPABILITIES);
        verify(mCallbacks, timeout(HANDLER_TIMEOUT_MS)).notifyNetworkTested(
                eq(NETWORK_VALIDATION_PROBE_DNS | NETWORK_VALIDATION_PROBE_HTTPS), eq(null));
        verify(mCallbacks, timeout(HANDLER_TIMEOUT_MS)).notifyNetworkTestedWithExtras(
                eq(NETWORK_VALIDATION_PROBE_DNS | NETWORK_VALIDATION_PROBE_HTTPS), eq(null),
                anyLong(), argThat(getNotifyNetworkTestedBundleMatcher()));
        verify(mCallbacks, timeout(HANDLER_TIMEOUT_MS).times(1)).notifyProbeStatusChanged(
                eq(VALIDATION_RESULT_PRIVDNS_VALID), eq(NETWORK_VALIDATION_PROBE_DNS
                | NETWORK_VALIDATION_PROBE_HTTPS));
@@ -1047,8 +1065,9 @@ public class NetworkMonitorTest {

        wnm.forceReevaluation(Process.myUid());
        verify(mCallbacks, timeout(HANDLER_TIMEOUT_MS).atLeastOnce())
                .notifyNetworkTested(eq(VALIDATION_RESULT_VALID | NETWORK_VALIDATION_PROBE_PRIVDNS),
                        eq(null));
                .notifyNetworkTestedWithExtras(eq(VALIDATION_RESULT_VALID
                        | NETWORK_VALIDATION_PROBE_PRIVDNS), eq(null), anyLong(),
                        argThat(getNotifyNetworkTestedBundleMatcher()));
        verify(mCallbacks, timeout(HANDLER_TIMEOUT_MS).times(1)).notifyProbeStatusChanged(
                eq(VALIDATION_RESULT_PRIVDNS_VALID), eq(VALIDATION_RESULT_PRIVDNS_VALID));

@@ -1060,8 +1079,9 @@ public class NetworkMonitorTest {
        // Strict mode hostname resolve fail. Expect only notification for evaluation fail. No probe
        // notification.
        verify(mCallbacks, timeout(HANDLER_TIMEOUT_MS))
                .notifyNetworkTested(eq(NETWORK_VALIDATION_PROBE_DNS
                        | NETWORK_VALIDATION_PROBE_HTTPS), eq(null));
                .notifyNetworkTestedWithExtras(eq(NETWORK_VALIDATION_PROBE_DNS
                        | NETWORK_VALIDATION_PROBE_HTTPS), eq(null), anyLong(),
                        argThat(getNotifyNetworkTestedBundleMatcher()));
        verify(mCallbacks, timeout(HANDLER_TIMEOUT_MS).times(1)).notifyProbeStatusChanged(
                eq(VALIDATION_RESULT_PRIVDNS_VALID), eq(NETWORK_VALIDATION_PROBE_DNS
                | NETWORK_VALIDATION_PROBE_HTTPS));
@@ -1072,8 +1092,9 @@ public class NetworkMonitorTest {
        mFakeDns.setNonBypassPrivateDnsWorking(false);
        wnm.notifyPrivateDnsSettingsChanged(new PrivateDnsConfig("dns.google",
                new InetAddress[0]));
        verify(mCallbacks, timeout(HANDLER_TIMEOUT_MS)).notifyNetworkTested(
                eq(NETWORK_VALIDATION_PROBE_DNS | NETWORK_VALIDATION_PROBE_HTTPS), eq(null));
        verify(mCallbacks, timeout(HANDLER_TIMEOUT_MS)).notifyNetworkTestedWithExtras(
                eq(NETWORK_VALIDATION_PROBE_DNS | NETWORK_VALIDATION_PROBE_HTTPS), eq(null),
                anyLong(), argThat(getNotifyNetworkTestedBundleMatcher()));
        // NetworkMonitor will check if the probes has changed or not, if the probes has not
        // changed, the callback won't be fired.
        verify(mCallbacks, never()).notifyProbeStatusChanged(
@@ -1085,8 +1106,9 @@ public class NetworkMonitorTest {
        mFakeDns.setNonBypassPrivateDnsWorking(true);
        wnm.forceReevaluation(Process.myUid());
        verify(mCallbacks, timeout(HANDLER_TIMEOUT_MS).atLeastOnce())
                .notifyNetworkTested(
                        eq(VALIDATION_RESULT_VALID | NETWORK_VALIDATION_PROBE_PRIVDNS), eq(null));
                .notifyNetworkTestedWithExtras(
                        eq(VALIDATION_RESULT_VALID | NETWORK_VALIDATION_PROBE_PRIVDNS), eq(null),
                        anyLong(), argThat(getNotifyNetworkTestedBundleMatcher()));
        verify(mCallbacks, timeout(HANDLER_TIMEOUT_MS).times(1)).notifyProbeStatusChanged(
                eq(VALIDATION_RESULT_PRIVDNS_VALID), eq(VALIDATION_RESULT_PRIVDNS_VALID));
    }
@@ -1154,8 +1176,9 @@ public class NetworkMonitorTest {
        resetCallbacks();
        nm.setAcceptPartialConnectivity();
        // Expect to update evaluation result notifications to CS.
        verify(mCallbacks, timeout(HANDLER_TIMEOUT_MS).times(1)).notifyNetworkTested(
                eq(VALIDATION_RESULT_PARTIAL | NETWORK_VALIDATION_RESULT_VALID), eq(null));
        verify(mCallbacks, timeout(HANDLER_TIMEOUT_MS).times(1)).notifyNetworkTestedWithExtras(
                eq(VALIDATION_RESULT_PARTIAL | NETWORK_VALIDATION_RESULT_VALID), eq(null),
                anyLong(), argThat(getNotifyNetworkTestedBundleMatcher()));
    }

    @Test
@@ -1230,8 +1253,25 @@ public class NetworkMonitorTest {
        final ArgumentCaptor<Integer> intCaptor = ArgumentCaptor.forClass(Integer.class);
        // Expect to send HTTP, HTTPs, FALLBACK and evaluation results.
        verify(mCallbacks, timeout(HANDLER_TIMEOUT_MS))
            .notifyNetworkTested(eq(NETWORK_VALIDATION_PROBE_DNS |
                    NETWORK_VALIDATION_PROBE_FALLBACK | NETWORK_VALIDATION_RESULT_PARTIAL), any());
                .notifyNetworkTestedWithExtras(eq(NETWORK_VALIDATION_PROBE_DNS
                        | NETWORK_VALIDATION_PROBE_FALLBACK | NETWORK_VALIDATION_RESULT_PARTIAL),
                        any(), anyLong(), argThat(getNotifyNetworkTestedBundleMatcher()));
    }

    @Test
    public void testNotifyNetwork_NotifyNetworkTestedOldInterfaceVersion() throws Exception {
        // Use old interface version so notifyNetworkTested is used over
        // notifyNetworkTestedWithExtras
        resetCallbacks(5);

        // Trigger Network validation
        setStatus(mHttpsConnection, 204);
        setStatus(mHttpConnection, 204);
        final NetworkMonitor nm = makeMonitor(METERED_CAPABILITIES);
        nm.notifyNetworkConnected(TEST_LINK_PROPERTIES, METERED_CAPABILITIES);

        verify(mCallbacks, timeout(HANDLER_TIMEOUT_MS))
                .notifyNetworkTested(eq(VALIDATION_RESULT_VALID), any());
    }

    @Test
@@ -1250,7 +1290,8 @@ public class NetworkMonitorTest {
        resetCallbacks();

        nm.reportHttpProbeResult(NETWORK_VALIDATION_PROBE_HTTP, CaptivePortalProbeResult.SUCCESS);
        // Verify result should be appended and notifyNetworkTested callback is triggered once.
        // Verify result should be appended and notifyNetworkTestedWithExtras callback is triggered
        // once.
        assertEquals(nm.getEvaluationState().getNetworkTestResult(),
                VALIDATION_RESULT_VALID | NETWORK_VALIDATION_PROBE_HTTP);

@@ -1266,21 +1307,23 @@ public class NetworkMonitorTest {

        nm.getEvaluationState().reportEvaluationResult(NETWORK_VALIDATION_RESULT_PARTIAL,
                null /* redirectUrl */);
        verify(mCallbacks, timeout(HANDLER_TIMEOUT_MS).times(1)).notifyNetworkTested(
        verify(mCallbacks, timeout(HANDLER_TIMEOUT_MS).times(1)).notifyNetworkTestedWithExtras(
                eq(NETWORK_VALIDATION_PROBE_DNS | NETWORK_VALIDATION_PROBE_HTTPS
                | NETWORK_VALIDATION_RESULT_PARTIAL), eq(null));
                | NETWORK_VALIDATION_RESULT_PARTIAL), eq(null), anyLong(),
                argThat(getNotifyNetworkTestedBundleMatcher()));

        nm.getEvaluationState().reportEvaluationResult(
                NETWORK_VALIDATION_RESULT_VALID | NETWORK_VALIDATION_RESULT_PARTIAL,
                null /* redirectUrl */);
        verify(mCallbacks, timeout(HANDLER_TIMEOUT_MS).times(1)).notifyNetworkTested(
                eq(VALIDATION_RESULT_VALID | NETWORK_VALIDATION_RESULT_PARTIAL), eq(null));
        verify(mCallbacks, timeout(HANDLER_TIMEOUT_MS).times(1)).notifyNetworkTestedWithExtras(
                eq(VALIDATION_RESULT_VALID | NETWORK_VALIDATION_RESULT_PARTIAL), eq(null),
                anyLong(), argThat(getNotifyNetworkTestedBundleMatcher()));

        nm.getEvaluationState().reportEvaluationResult(VALIDATION_RESULT_INVALID,
                TEST_REDIRECT_URL);
        verify(mCallbacks, timeout(HANDLER_TIMEOUT_MS).times(1)).notifyNetworkTested(
        verify(mCallbacks, timeout(HANDLER_TIMEOUT_MS).times(1)).notifyNetworkTestedWithExtras(
                eq(NETWORK_VALIDATION_PROBE_DNS | NETWORK_VALIDATION_PROBE_HTTPS),
                eq(TEST_REDIRECT_URL));
                eq(TEST_REDIRECT_URL), anyLong(), argThat(getNotifyNetworkTestedBundleMatcher()));
    }

    private void makeDnsTimeoutEvent(WrappedNetworkMonitor wrappedMonitor, int count) {
@@ -1392,7 +1435,9 @@ public class NetworkMonitorTest {
        monitor.notifyNetworkConnected(TEST_LINK_PROPERTIES, nc);
        try {
            verify(mCallbacks, timeout(HANDLER_TIMEOUT_MS))
                    .notifyNetworkTested(eq(testResult), mNetworkTestedRedirectUrlCaptor.capture());
                    .notifyNetworkTestedWithExtras(eq(testResult),
                            mNetworkTestedRedirectUrlCaptor.capture(), anyLong(),
                            argThat(getNotifyNetworkTestedBundleMatcher()));
        } catch (RemoteException e) {
            fail("Unexpected exception: " + e);
        }
@@ -1424,5 +1469,21 @@ public class NetworkMonitorTest {
        }
    }

    private ArgumentMatcher<PersistableBundle> getNotifyNetworkTestedBundleMatcher() {
        return bundle ->
                bundle.containsKey(KEY_NETWORK_PROBES_ATTEMPTED_BITMASK)
                && bundle.containsKey(KEY_NETWORK_PROBES_SUCCEEDED_BITMASK)
                && bundle.containsKey(KEY_NETWORK_VALIDATION_RESULT);
    }

    private ArgumentMatcher<PersistableBundle> getDataStallDnsBundleMatcher() {
        return bundle -> bundle.containsKey(KEY_DNS_CONSECUTIVE_TIMEOUTS);
    }

    private ArgumentMatcher<PersistableBundle> getDataStallTcpBundleMatcher() {
        return bundle ->
                bundle.containsKey(KEY_TCP_METRICS_COLLECTION_PERIOD_MILLIS)
                && bundle.containsKey(KEY_TCP_PACKET_FAIL_RATE);
    }
}