// Copyright 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

package org.chromium.net;

import static android.net.NetworkCapabilities.NET_CAPABILITY_INTERNET;
import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR;
import static android.net.NetworkCapabilities.TRANSPORT_VPN;
import static android.net.NetworkCapabilities.TRANSPORT_WIFI;

import android.annotation.SuppressLint;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.ContextWrapper;
import android.content.Intent;
import android.content.IntentFilter;
import android.net.ConnectivityManager;
import android.net.ConnectivityManager.NetworkCallback;
import android.net.Network;
import android.net.NetworkCapabilities;
import android.net.NetworkRequest;
import android.os.Build;
import android.os.Handler;
import android.os.Looper;
import android.os.StrictMode;
import android.support.test.InstrumentationRegistry;
import android.support.test.annotation.UiThreadTest;
import android.support.test.filters.MediumTest;
import android.support.test.rule.UiThreadTestRule;
import android.telephony.TelephonyManager;

import org.junit.Assert;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;

import org.chromium.base.ApplicationState;
import org.chromium.base.BuildInfo;
import org.chromium.base.ContextUtils;
import org.chromium.base.ThreadUtils;
import org.chromium.base.library_loader.LibraryLoader;
import org.chromium.base.library_loader.LibraryProcessType;
import org.chromium.base.test.BaseJUnit4ClassRunner;
import org.chromium.base.test.util.Feature;
import org.chromium.base.test.util.MinAndroidSdkLevel;
import org.chromium.net.NetworkChangeNotifierAutoDetect.ConnectivityManagerDelegate;
import org.chromium.net.NetworkChangeNotifierAutoDetect.NetworkState;
import org.chromium.net.NetworkChangeNotifierAutoDetect.WifiManagerDelegate;
import org.chromium.net.test.util.NetworkChangeNotifierTestUtil;

import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.concurrent.Callable;
import java.util.concurrent.FutureTask;

/**
 * Tests for org.chromium.net.NetworkChangeNotifier.
 */
@RunWith(BaseJUnit4ClassRunner.class)
@SuppressLint("NewApi")
public class NetworkChangeNotifierTest {
    @Rule
    public UiThreadTestRule mUiThreadRule = new UiThreadTestRule();

    /**
     * Listens for alerts fired by the NetworkChangeNotifier when network status changes.
     */
    private static class NetworkChangeNotifierTestObserver
            implements NetworkChangeNotifier.ConnectionTypeObserver {
        private boolean mReceivedNotification;

        @Override
        public void onConnectionTypeChanged(int connectionType) {
            mReceivedNotification = true;
        }

        public boolean hasReceivedNotification() {
            return mReceivedNotification;
        }

        public void resetHasReceivedNotification() {
            mReceivedNotification = false;
        }
    }

    /**
      * Listens for native notifications of max bandwidth change.
      */
    private static class TestNetworkChangeNotifier extends NetworkChangeNotifier {
        @Override
        void notifyObserversOfConnectionSubtypeChange(int newConnectionSubtype) {
            mReceivedConnectionSubtypeNotification = true;
        }

        public boolean hasReceivedConnectionSubtypeNotification() {
            return mReceivedConnectionSubtypeNotification;
        }

        public void resetHasReceivedConnectionSubtypeNotification() {
            mReceivedConnectionSubtypeNotification = false;
        }

        private boolean mReceivedConnectionSubtypeNotification;
    }

    private static class Helper {
        private static final Constructor<Network> sNetworkConstructor;

        static {
            try {
                sNetworkConstructor = (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP)
                        ? Network.class.getConstructor(Integer.TYPE)
                        : null;
            } catch (NoSuchMethodException | SecurityException e) {
                throw new RuntimeException("Unable to get Network constructor", e);
            }
        }

        static NetworkCapabilities getCapabilities(int transport) {
            // Create a NetworkRequest with corresponding capabilities
            NetworkRequest request = new NetworkRequest.Builder()
                                             .addCapability(NET_CAPABILITY_INTERNET)
                                             .addTransportType(transport)
                                             .build();
            // Extract the NetworkCapabilities from the NetworkRequest.
            try {
                return (NetworkCapabilities) request.getClass()
                        .getDeclaredField("networkCapabilities")
                        .get(request);
            } catch (NoSuchFieldException | IllegalAccessException e) {
                return null;
            }
        }
        // Create Network object given a NetID.
        static Network netIdToNetwork(int netId) {
            try {
                return sNetworkConstructor.newInstance(netId);
            } catch (
            InstantiationException | InvocationTargetException | IllegalAccessException e) {
                throw new IllegalStateException("Trying to create Network when not allowed");
            }
        }
    }

    private static void triggerApplicationStateChange(
            final RegistrationPolicyApplicationStatus policy, final int applicationState) {
        ThreadUtils.runOnUiThreadBlocking(new Runnable() {
            @Override
            public void run() {
                policy.onApplicationStateChange(applicationState);
            }
        });
    }

    /**
     * Mocks out calls to the ConnectivityManager.
     */
    private class MockConnectivityManagerDelegate extends ConnectivityManagerDelegate {
        // A network we're pretending is currently connected.
        private class MockNetwork {
            // Network identifier
            final int mNetId;
            // Transport, one of android.net.NetworkCapabilities.TRANSPORT_*
            final int mTransport;
            // Is this VPN accessible to the current user?
            final boolean mVpnAccessible;

            NetworkCapabilities getCapabilities() {
                return Helper.getCapabilities(mTransport);
            }

            /**
             * @param netId Network identifier
             * @param transport Transport, one of android.net.NetworkCapabilities.TRANSPORT_*
             * @param vpnAccessible Is this VPN accessible to the current user?
             */
            MockNetwork(int netId, int transport, boolean vpnAccessible) {
                mNetId = netId;
                mTransport = transport;
                mVpnAccessible = vpnAccessible;
            }
        }

        // List of networks we're pretending are currently connected.
        private final ArrayList<MockNetwork> mMockNetworks = new ArrayList<>();

        private boolean mActiveNetworkExists;
        private int mNetworkType;
        private int mNetworkSubtype;
        private boolean mIsPrivateDnsActive;
        private NetworkCallback mLastRegisteredNetworkCallback;
        private NetworkCallback mLastRegisteredDefaultNetworkCallback;

        @Override
        public NetworkState getNetworkState(WifiManagerDelegate wifiManagerDelegate) {
            return new NetworkState(mActiveNetworkExists, mNetworkType, mNetworkSubtype,
                    mNetworkType == ConnectivityManager.TYPE_WIFI
                            ? wifiManagerDelegate.getWifiSsid()
                            : null,
                    mIsPrivateDnsActive);
        }

        @Override
        protected NetworkCapabilities getNetworkCapabilities(Network network) {
            int netId = demungeNetId(NetworkChangeNotifierAutoDetect.networkToNetId(network));
            for (MockNetwork mockNetwork : mMockNetworks) {
                if (netId == mockNetwork.mNetId) {
                    return mockNetwork.getCapabilities();
                }
            }
            return null;
        }

        @Override
        protected boolean vpnAccessible(Network network) {
            int netId = demungeNetId(NetworkChangeNotifierAutoDetect.networkToNetId(network));
            for (MockNetwork mockNetwork : mMockNetworks) {
                if (netId == mockNetwork.mNetId) {
                    return mockNetwork.mVpnAccessible;
                }
            }
            return false;
        }

        @Override
        protected Network[] getAllNetworksUnfiltered() {
            Network[] networks = new Network[mMockNetworks.size()];
            for (int i = 0; i < networks.length; i++) {
                networks[i] = Helper.netIdToNetwork(mMockNetworks.get(i).mNetId);
            }
            return networks;
        }

        // Dummy implementations to avoid NullPointerExceptions in default implementations:

        @Override
        public Network getDefaultNetwork() {
            return null;
        }

        @Override
        public int getConnectionType(Network network) {
            return ConnectionType.CONNECTION_NONE;
        }

        @Override
        public void unregisterNetworkCallback(NetworkCallback networkCallback) {}

        // Dummy implementation that also records the last registered callback.
        @Override
        public void registerNetworkCallback(
                NetworkRequest networkRequest, NetworkCallback networkCallback, Handler handler) {
            mLastRegisteredNetworkCallback = networkCallback;
        }

        // Dummy implementation that also records the last registered callback.
        @Override
        public void registerDefaultNetworkCallback(
                NetworkCallback networkCallback, Handler handler) {
            mLastRegisteredDefaultNetworkCallback = networkCallback;
        }

        public void setActiveNetworkExists(boolean networkExists) {
            mActiveNetworkExists = networkExists;
        }

        public void setNetworkType(int networkType) {
            mNetworkType = networkType;
        }

        public void setNetworkSubtype(int networkSubtype) {
            mNetworkSubtype = networkSubtype;
        }

        public void setIsPrivateDnsActive(boolean isPrivateDnsActive) {
            mIsPrivateDnsActive = isPrivateDnsActive;
        }

        public NetworkCallback getLastRegisteredNetworkCallback() {
            return mLastRegisteredNetworkCallback;
        }

        public NetworkCallback getDefaultNetworkCallback() {
            return mLastRegisteredDefaultNetworkCallback;
        }

        /**
         * Pretends a network connects.
         * @param netId Network identifier
         * @param transport Transport, one of android.net.NetworkCapabilities.TRANSPORT_*
         * @param vpnAccessible Is this VPN accessible to the current user?
         */
        public void addNetwork(int netId, int transport, boolean vpnAccessible) {
            mMockNetworks.add(new MockNetwork(netId, transport, vpnAccessible));
            mLastRegisteredNetworkCallback.onAvailable(Helper.netIdToNetwork(netId));
        }

        /**
         * Pretends a network disconnects.
         * @param netId Network identifier
         */
        public void removeNetwork(int netId) {
            for (MockNetwork mockNetwork : mMockNetworks) {
                if (mockNetwork.mNetId == netId) {
                    mMockNetworks.remove(mockNetwork);
                    mLastRegisteredNetworkCallback.onLost(Helper.netIdToNetwork(netId));
                    break;
                }
            }
        }
    }

    /**
     * Mocks out calls to the WifiManager.
     */
    private static class MockWifiManagerDelegate extends WifiManagerDelegate {
        private String mWifiSSID;

        @Override
        public String getWifiSsid() {
            return mWifiSSID;
        }

        public void setWifiSSID(String wifiSSID) {
            mWifiSSID = wifiSSID;
        }
    }

    private static int demungeNetId(long netId) {
        // On Marshmallow, demunge the NetID to undo munging done in Network.getNetworkHandle().
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
            netId >>= 32;
        }
        // Now that the NetID has been demunged it is a true NetID which means it's only a 16-bit
        // value (see ConnectivityService.MAX_NET_ID) so it should be safe to cast to int.
        return (int) netId;
    }

    // Types of network changes. Each is associated with a NetworkChangeNotifierAutoDetect.Observer
    // callback, and NONE is provided to indicate no callback observed.
    private static enum ChangeType { NONE, CONNECT, SOON_TO_DISCONNECT, DISCONNECT, PURGE_LIST }

    // Recorded information about a network change that took place.
    private static class ChangeInfo {
        // The type of change.
        final ChangeType mChangeType;
        // The network identifier of the network changing.
        final int mNetId;

        /**
         * @param changeType the type of change.
         * @param netId the network identifier of the network changing.
         */
        ChangeInfo(ChangeType changeType, long netId) {
            mChangeType = changeType;
            mNetId = demungeNetId(netId);
        }
    }

    // NetworkChangeNotifierAutoDetect.Observer used to verify proper notifications are sent out.
    // Notifications come back on UI thread. assertLastChange() called on test thread.
    private static class TestNetworkChangeNotifierAutoDetectObserver
            implements NetworkChangeNotifierAutoDetect.Observer {
        // The list of network changes that have been witnessed.
        final ArrayList<ChangeInfo> mChanges = new ArrayList<>();

        @Override
        public void onConnectionTypeChanged(int newConnectionType) {}
        @Override
        public void onConnectionSubtypeChanged(int newConnectionSubtype) {}

        @Override
        public void onNetworkConnect(long netId, int connectionType) {
            ThreadUtils.assertOnUiThread();
            mChanges.add(new ChangeInfo(ChangeType.CONNECT, netId));
        }

        @Override
        public void onNetworkSoonToDisconnect(long netId) {
            ThreadUtils.assertOnUiThread();
            mChanges.add(new ChangeInfo(ChangeType.SOON_TO_DISCONNECT, netId));
        }

        @Override
        public void onNetworkDisconnect(long netId) {
            ThreadUtils.assertOnUiThread();
            mChanges.add(new ChangeInfo(ChangeType.DISCONNECT, netId));
        }

        @Override
        public void purgeActiveNetworkList(long[] activeNetIds) {
            ThreadUtils.assertOnUiThread();
            if (activeNetIds.length == 1) {
                mChanges.add(new ChangeInfo(ChangeType.PURGE_LIST, activeNetIds[0]));
            } else {
                mChanges.add(new ChangeInfo(ChangeType.PURGE_LIST, NetId.INVALID));
            }
        }

        // Verify last notification was the expected one.
        public void assertLastChange(ChangeType type, int netId) throws Exception {
            // Make sure notification processed.
            NetworkChangeNotifierTestUtil.flushUiThreadTaskQueue();
            Assert.assertNotNull(mChanges.get(0));
            Assert.assertEquals(type, mChanges.get(0).mChangeType);
            Assert.assertEquals(netId, mChanges.get(0).mNetId);
            mChanges.clear();
        }
    }

    // Network.Network(int netId) pointer.
    private TestNetworkChangeNotifier mNotifier;
    private NetworkChangeNotifierAutoDetect mReceiver;
    private MockConnectivityManagerDelegate mConnectivityDelegate;
    private MockWifiManagerDelegate mWifiDelegate;

    private static enum WatchForChanges {
        ALWAYS,
        ONLY_WHEN_APP_IN_FOREGROUND,
    }

    /**
     * Helper method to create a notifier and delegates for testing.
     * @param watchForChanges indicates whether app wants to watch for changes always or only when
     *            it is in the foreground.
     */
    private void createTestNotifier(WatchForChanges watchForChanges) {
        Context context = new ContextWrapper(InstrumentationRegistry.getInstrumentation()
                                                     .getTargetContext()
                                                     .getApplicationContext()) {
            // Mock out to avoid unintended system interaction.
            @Override
            public Intent registerReceiver(BroadcastReceiver receiver, IntentFilter filter) {
                // Should not be used starting with Pie.
                Assert.assertFalse(BuildInfo.isAtLeastP());
                return null;
            }

            @Override
            public void unregisterReceiver(BroadcastReceiver receiver) {}

            // Don't allow escaping the mock via the application context.
            @Override
            public Context getApplicationContext() {
                return this;
            }
        };
        ContextUtils.initApplicationContextForTests(context);
        mNotifier = new TestNetworkChangeNotifier();
        NetworkChangeNotifier.resetInstanceForTests(mNotifier);
        if (watchForChanges == WatchForChanges.ALWAYS) {
            NetworkChangeNotifier.registerToReceiveNotificationsAlways();
        } else {
            NetworkChangeNotifier.setAutoDetectConnectivityState(true);
        }
        mReceiver = NetworkChangeNotifier.getAutoDetectorForTest();
        Assert.assertNotNull(mReceiver);

        mConnectivityDelegate =
                new MockConnectivityManagerDelegate();
        mConnectivityDelegate.setActiveNetworkExists(true);
        mReceiver.setConnectivityManagerDelegateForTests(mConnectivityDelegate);

        mWifiDelegate = new MockWifiManagerDelegate();
        mReceiver.setWifiManagerDelegateForTests(mWifiDelegate);
        mWifiDelegate.setWifiSSID("foo");
    }

    private int getCurrentConnectionSubtype() {
        return mReceiver.getCurrentNetworkState().getConnectionSubtype();
    }

    private int getCurrentConnectionType() {
        return mReceiver.getCurrentNetworkState().getConnectionType();
    }

    @Before
    public void setUp() throws Throwable {
        LibraryLoader.getInstance().ensureInitialized(LibraryProcessType.PROCESS_BROWSER);

        mUiThreadRule.runOnUiThread(new Runnable() {
            @Override
            public void run() {
                createTestNotifier(WatchForChanges.ONLY_WHEN_APP_IN_FOREGROUND);
            }
        });
    }

    /**
     * Tests that the receiver registers for connectivity
     * broadcasts during construction when the registration policy dictates.
     */
    @Test
    @UiThreadTest
    @MediumTest
    @Feature({"Android-AppBase"})
    public void testNetworkChangeNotifierRegistersWhenPolicyDictates() {
        NetworkChangeNotifierAutoDetect.Observer observer =
                new TestNetworkChangeNotifierAutoDetectObserver();

        NetworkChangeNotifierAutoDetect receiver = new NetworkChangeNotifierAutoDetect(
                observer, new RegistrationPolicyApplicationStatus() {
                    @Override
                    int getApplicationState() {
                        return ApplicationState.HAS_RUNNING_ACTIVITIES;
                    }
                });

        Assert.assertTrue(receiver.isReceiverRegisteredForTesting());

        receiver = new NetworkChangeNotifierAutoDetect(
                observer, new RegistrationPolicyApplicationStatus() {
                    @Override
                    int getApplicationState() {
                        return ApplicationState.HAS_PAUSED_ACTIVITIES;
                    }
                });

        Assert.assertFalse(receiver.isReceiverRegisteredForTesting());
    }

    /**
     * Tests that the receiver toggles registration for connectivity intents based on activity
     * state.
     */
    @Test
    @UiThreadTest
    @MediumTest
    @Feature({"Android-AppBase"})
    public void testNetworkChangeNotifierRegistersForIntents() {
        RegistrationPolicyApplicationStatus policy =
                (RegistrationPolicyApplicationStatus) mReceiver.getRegistrationPolicy();
        triggerApplicationStateChange(policy, ApplicationState.HAS_RUNNING_ACTIVITIES);
        Assert.assertTrue(mReceiver.isReceiverRegisteredForTesting());

        triggerApplicationStateChange(policy, ApplicationState.HAS_PAUSED_ACTIVITIES);
        Assert.assertFalse(mReceiver.isReceiverRegisteredForTesting());

        triggerApplicationStateChange(policy, ApplicationState.HAS_RUNNING_ACTIVITIES);
        Assert.assertTrue(mReceiver.isReceiverRegisteredForTesting());
    }

    /**
     * Tests that changing the network type changes the connection subtype.
     */
    @Test
    @UiThreadTest
    @MediumTest
    @Feature({"Android-AppBase"})
    public void testNetworkChangeNotifierConnectionSubtypeEthernet() {
        // Show that for Ethernet the link speed is unknown (+Infinity).
        mConnectivityDelegate.setNetworkType(ConnectivityManager.TYPE_ETHERNET);
        Assert.assertEquals(ConnectionType.CONNECTION_ETHERNET, getCurrentConnectionType());
        Assert.assertEquals(ConnectionSubtype.SUBTYPE_UNKNOWN, getCurrentConnectionSubtype());
    }

    @Test
    @UiThreadTest
    @MediumTest
    @Feature({"Android-AppBase"})
    public void testNetworkChangeNotifierConnectionSubtypeWifi() {
        // Show that for WiFi the link speed is unknown (+Infinity).
        mConnectivityDelegate.setNetworkType(ConnectivityManager.TYPE_WIFI);
        Assert.assertEquals(ConnectionType.CONNECTION_WIFI, getCurrentConnectionType());
        Assert.assertEquals(ConnectionSubtype.SUBTYPE_UNKNOWN, getCurrentConnectionSubtype());
    }

    @Test
    @UiThreadTest
    @MediumTest
    @Feature({"Android-AppBase"})
    public void testNetworkChangeNotifierConnectionSubtypeWiMax() {
        // Show that for WiMax the link speed is unknown (+Infinity), although the type is 4g.
        // TODO(jkarlin): Add support for CONNECTION_WIMAX as specified in
        // http://w3c.github.io/netinfo/.
        mConnectivityDelegate.setNetworkType(ConnectivityManager.TYPE_WIMAX);
        Assert.assertEquals(ConnectionType.CONNECTION_4G, getCurrentConnectionType());
        Assert.assertEquals(ConnectionSubtype.SUBTYPE_UNKNOWN, getCurrentConnectionSubtype());
    }

    @Test
    @UiThreadTest
    @MediumTest
    @Feature({"Android-AppBase"})
    public void testNetworkChangeNotifierConnectionSubtypeBluetooth() {
        // Show that for bluetooth the link speed is unknown (+Infinity).
        mConnectivityDelegate.setNetworkType(ConnectivityManager.TYPE_BLUETOOTH);
        Assert.assertEquals(ConnectionType.CONNECTION_BLUETOOTH, getCurrentConnectionType());
        Assert.assertEquals(ConnectionSubtype.SUBTYPE_UNKNOWN, getCurrentConnectionSubtype());
    }

    @Test
    @UiThreadTest
    @MediumTest
    @Feature({"Android-AppBase"})
    public void testNetworkChangeNotifierConnectionSubtypeMobile() {
        // Test that for mobile types the subtype is used to determine the connection subtype.
        mConnectivityDelegate.setNetworkType(ConnectivityManager.TYPE_MOBILE);
        mConnectivityDelegate.setNetworkSubtype(TelephonyManager.NETWORK_TYPE_LTE);
        Assert.assertEquals(ConnectionType.CONNECTION_4G, getCurrentConnectionType());
        Assert.assertEquals(ConnectionSubtype.SUBTYPE_LTE, getCurrentConnectionSubtype());
    }

    /**
     * Indicate to NetworkChangeNotifierAutoDetect that a connectivity change has occurred.
     * Uses same signals that system would use.
     */
    private void notifyConnectivityChange() {
        if (BuildInfo.isAtLeastP()) {
            mConnectivityDelegate.getDefaultNetworkCallback().onAvailable(null);
        } else {
            Intent connectivityIntent = new Intent(ConnectivityManager.CONNECTIVITY_ACTION);
            mReceiver.onReceive(InstrumentationRegistry.getTargetContext(), connectivityIntent);
        }
    }

    /**
     * Tests that when Chrome gets an intent indicating a change in network connectivity, it sends a
     * notification to Java observers.
     */
    @Test
    @UiThreadTest
    @MediumTest
    @Feature({"Android-AppBase"})
    public void testNetworkChangeNotifierJavaObservers() {
        mReceiver.register();
        // Initialize the NetworkChangeNotifier with a connection.
        Intent connectivityIntent = new Intent(ConnectivityManager.CONNECTIVITY_ACTION);
        mReceiver.onReceive(InstrumentationRegistry.getTargetContext(), connectivityIntent);

        // We shouldn't be re-notified if the connection hasn't actually changed.
        NetworkChangeNotifierTestObserver observer = new NetworkChangeNotifierTestObserver();
        NetworkChangeNotifier.addConnectionTypeObserver(observer);
        notifyConnectivityChange();
        Assert.assertFalse(observer.hasReceivedNotification());

        // We shouldn't be notified if we're connected to non-Wifi and the Wifi SSID changes.
        mWifiDelegate.setWifiSSID("bar");
        notifyConnectivityChange();
        Assert.assertFalse(observer.hasReceivedNotification());
        // We should be notified when we change to Wifi.
        mConnectivityDelegate.setNetworkType(ConnectivityManager.TYPE_WIFI);
        notifyConnectivityChange();
        Assert.assertTrue(observer.hasReceivedNotification());
        observer.resetHasReceivedNotification();
        // We should be notified when the Wifi SSID changes.
        mWifiDelegate.setWifiSSID("foo");
        notifyConnectivityChange();
        Assert.assertTrue(observer.hasReceivedNotification());
        observer.resetHasReceivedNotification();
        // We shouldn't be re-notified if the Wifi SSID hasn't actually changed.
        notifyConnectivityChange();
        Assert.assertFalse(observer.hasReceivedNotification());

        // We should be notified if use of DNS-over-TLS changes.
        if (BuildInfo.isAtLeastP()) {
            // Verify notification for enabling.
            mConnectivityDelegate.setIsPrivateDnsActive(true);
            mConnectivityDelegate.getDefaultNetworkCallback().onLinkPropertiesChanged(null, null);
            Assert.assertTrue(observer.hasReceivedNotification());
            observer.resetHasReceivedNotification();
            // Verify no notification for no change.
            mConnectivityDelegate.getDefaultNetworkCallback().onLinkPropertiesChanged(null, null);
            Assert.assertFalse(observer.hasReceivedNotification());
            // Verify notification for disbling.
            mConnectivityDelegate.setIsPrivateDnsActive(false);
            mConnectivityDelegate.getDefaultNetworkCallback().onLinkPropertiesChanged(null, null);
            Assert.assertTrue(observer.hasReceivedNotification());
            observer.resetHasReceivedNotification();
        }

        // Mimic that connectivity has been lost and ensure that Chrome notifies our observer.
        mConnectivityDelegate.setActiveNetworkExists(false);
        if (BuildInfo.isAtLeastP()) {
            mConnectivityDelegate.getDefaultNetworkCallback().onLost(null);
        } else {
            mReceiver.onReceive(InstrumentationRegistry.getTargetContext(), connectivityIntent);
        }
        Assert.assertTrue(observer.hasReceivedNotification());

        observer.resetHasReceivedNotification();
        // Pretend we got moved to the background.
        final RegistrationPolicyApplicationStatus policy =
                (RegistrationPolicyApplicationStatus) mReceiver.getRegistrationPolicy();
        triggerApplicationStateChange(policy, ApplicationState.HAS_PAUSED_ACTIVITIES);
        // Change the state.
        mConnectivityDelegate.setActiveNetworkExists(true);
        mConnectivityDelegate.setNetworkType(ConnectivityManager.TYPE_WIFI);
        // The NetworkChangeNotifierAutoDetect doesn't receive any notification while we are in the
        // background, but when we get back to the foreground the state changed should be detected
        // and a notification sent.
        triggerApplicationStateChange(policy, ApplicationState.HAS_RUNNING_ACTIVITIES);
        Assert.assertTrue(observer.hasReceivedNotification());
    }

    /**
     * Tests that when Chrome gets an intent indicating a change in max bandwidth, it sends a
     * notification to Java observers.
     */
    @Test
    @UiThreadTest
    @MediumTest
    @Feature({"Android-AppBase"})
    public void testNetworkChangeNotifierConnectionSubtypeNotifications() {
        mReceiver.register();
        // Initialize the NetworkChangeNotifier with a connection.
        mConnectivityDelegate.setActiveNetworkExists(true);
        mConnectivityDelegate.setNetworkType(ConnectivityManager.TYPE_WIFI);
        Intent connectivityIntent = new Intent(ConnectivityManager.CONNECTIVITY_ACTION);
        mReceiver.onReceive(InstrumentationRegistry.getTargetContext(), connectivityIntent);
        Assert.assertTrue(mNotifier.hasReceivedConnectionSubtypeNotification());
        mNotifier.resetHasReceivedConnectionSubtypeNotification();

        // We shouldn't be re-notified if the connection hasn't actually changed.
        NetworkChangeNotifierTestObserver observer = new NetworkChangeNotifierTestObserver();
        NetworkChangeNotifier.addConnectionTypeObserver(observer);
        mReceiver.onReceive(InstrumentationRegistry.getTargetContext(), connectivityIntent);
        Assert.assertFalse(mNotifier.hasReceivedConnectionSubtypeNotification());

        // We should be notified if bandwidth and connection type changed.
        mConnectivityDelegate.setNetworkType(ConnectivityManager.TYPE_ETHERNET);
        mReceiver.onReceive(InstrumentationRegistry.getTargetContext(), connectivityIntent);
        Assert.assertTrue(mNotifier.hasReceivedConnectionSubtypeNotification());
        mNotifier.resetHasReceivedConnectionSubtypeNotification();

        // We should be notified if the connection type changed, but not the bandwidth.
        // Note that TYPE_ETHERNET and TYPE_BLUETOOTH have the same +INFINITY max bandwidth.
        // This test will fail if that changes.
        mConnectivityDelegate.setNetworkType(ConnectivityManager.TYPE_BLUETOOTH);
        mReceiver.onReceive(InstrumentationRegistry.getTargetContext(), connectivityIntent);
        Assert.assertTrue(mNotifier.hasReceivedConnectionSubtypeNotification());
    }

    /**
     * Tests that when setting {@code registerToReceiveNotificationsAlways()},
     * a NetworkChangeNotifierAutoDetect object is successfully created.
     */
    @Test
    @UiThreadTest
    @MediumTest
    @Feature({"Android-AppBase"})
    public void testCreateNetworkChangeNotifierAlwaysWatchForChanges() {
        createTestNotifier(WatchForChanges.ALWAYS);
        Assert.assertTrue(mReceiver.isReceiverRegisteredForTesting());

        // Make sure notifications can be received.
        NetworkChangeNotifierTestObserver observer = new NetworkChangeNotifierTestObserver();
        NetworkChangeNotifier.addConnectionTypeObserver(observer);
        Intent connectivityIntent = new Intent(ConnectivityManager.CONNECTIVITY_ACTION);
        mReceiver.onReceive(InstrumentationRegistry.getTargetContext(), connectivityIntent);
        Assert.assertTrue(observer.hasReceivedNotification());
    }

    /**
     * Tests that ConnectivityManagerDelegate doesn't crash. This test cannot rely on having any
     * active network connections so it cannot usefully check results, but it can at least check
     * that the functions don't crash.
     */
    @Test
    @UiThreadTest
    @MediumTest
    @Feature({"Android-AppBase"})
    public void testConnectivityManagerDelegateDoesNotCrash() {
        ConnectivityManagerDelegate delegate =
                new ConnectivityManagerDelegate(InstrumentationRegistry.getTargetContext());
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
            delegate.getNetworkState(null);
        } else {
            delegate.getNetworkState(
                    new WifiManagerDelegate(InstrumentationRegistry.getTargetContext()));
        }
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
            // getConnectionType(Network) doesn't crash upon invalid Network argument.
            Network invalidNetwork = Helper.netIdToNetwork(NetId.INVALID);
            Assert.assertEquals(
                    ConnectionType.CONNECTION_NONE, delegate.getConnectionType(invalidNetwork));

            Network[] networks = delegate.getAllNetworksUnfiltered();
            Assert.assertNotNull(networks);
            if (networks.length >= 1) {
                delegate.getConnectionType(networks[0]);
            }
            delegate.getDefaultNetwork();
            NetworkCallback networkCallback = new NetworkCallback();
            NetworkRequest networkRequest = new NetworkRequest.Builder().build();
            delegate.registerNetworkCallback(
                    networkRequest, networkCallback, new Handler(Looper.myLooper()));
            delegate.unregisterNetworkCallback(networkCallback);
        }
    }

    /**
     * Tests that NetworkChangeNotifierAutoDetect queryable APIs don't crash. This test cannot rely
     * on having any active network connections so it cannot usefully check results, but it can at
     * least check that the functions don't crash.
     */
    @Test
    @UiThreadTest
    @MediumTest
    @Feature({"Android-AppBase"})
    public void testQueryableAPIsDoNotCrash() {
        NetworkChangeNotifierAutoDetect.Observer observer =
                new TestNetworkChangeNotifierAutoDetectObserver();
        NetworkChangeNotifierAutoDetect ncn = new NetworkChangeNotifierAutoDetect(observer,
                new RegistrationPolicyAlwaysRegister());
        ncn.getNetworksAndTypes();
        ncn.getDefaultNetId();
    }

    /**
     * Tests that NetworkChangeNotifierAutoDetect query-able APIs return expected
     * values from the inserted mock ConnectivityManager.
     */
    @Test
    @UiThreadTest
    @MediumTest
    @Feature({"Android-AppBase"})
    public void testQueryableAPIsReturnExpectedValuesFromMockDelegate() throws Exception {
        NetworkChangeNotifierAutoDetect.Observer observer =
                new TestNetworkChangeNotifierAutoDetectObserver();

        NetworkChangeNotifierAutoDetect ncn = new NetworkChangeNotifierAutoDetect(
                observer, new RegistrationPolicyApplicationStatus() {
                    @Override
                    int getApplicationState() {
                        return ApplicationState.HAS_PAUSED_ACTIVITIES;
                    }
                });

        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
            Assert.assertEquals(0, ncn.getNetworksAndTypes().length);
            Assert.assertEquals(NetId.INVALID, ncn.getDefaultNetId());
            return;
        }

        // Insert a mocked dummy implementation for the ConnectivityDelegate.
        ncn.setConnectivityManagerDelegateForTests(new ConnectivityManagerDelegate() {
            public final Network[] mNetworks =
                    new Network[] {Helper.netIdToNetwork(111), Helper.netIdToNetwork(333)};

            @Override
            protected Network[] getAllNetworksUnfiltered() {
                return mNetworks;
            }

            @Override
            Network getDefaultNetwork() {
                return mNetworks[1];
            }

            @Override
            protected NetworkCapabilities getNetworkCapabilities(Network network) {
                return Helper.getCapabilities(TRANSPORT_WIFI);
            }

            @Override
            public int getConnectionType(Network network) {
                return ConnectionType.CONNECTION_NONE;
            }
        });

        // Verify that the mock delegate connectivity manager is being used
        // by the network change notifier auto-detector.
        Assert.assertEquals(333, demungeNetId(ncn.getDefaultNetId()));

        // The api {@link NetworkChangeNotifierAutoDetect#getNetworksAndTypes()}
        // returns an array of a repeated sequence of: (NetID, ConnectionType).
        // There are 4 entries in the array, two for each network.
        Assert.assertEquals(4, ncn.getNetworksAndTypes().length);
        Assert.assertEquals(111, demungeNetId(ncn.getNetworksAndTypes()[0]));
        Assert.assertEquals(ConnectionType.CONNECTION_NONE, ncn.getNetworksAndTypes()[1]);
        Assert.assertEquals(333, demungeNetId(ncn.getNetworksAndTypes()[2]));
        Assert.assertEquals(ConnectionType.CONNECTION_NONE, ncn.getNetworksAndTypes()[3]);
    }

    /**
     * Tests that callbacks are issued to Observers when NetworkChangeNotifierAutoDetect receives
     * the right signals (via its NetworkCallback).
     */
    @Test
    @MediumTest
    @Feature({"Android-AppBase"})
    @MinAndroidSdkLevel(Build.VERSION_CODES.LOLLIPOP)
    public void testNetworkCallbacks() throws Exception {
        // Setup NetworkChangeNotifierAutoDetect
        final TestNetworkChangeNotifierAutoDetectObserver observer =
                new TestNetworkChangeNotifierAutoDetectObserver();
        Callable<NetworkChangeNotifierAutoDetect> callable =
                new Callable<NetworkChangeNotifierAutoDetect>() {
                    @Override
                    public NetworkChangeNotifierAutoDetect call() {
                        return new NetworkChangeNotifierAutoDetect(
                                observer, new RegistrationPolicyApplicationStatus() {
                                    // This override prevents NetworkChangeNotifierAutoDetect from
                                    // registering for events right off the bat. We'll delay this
                                    // until our MockConnectivityManagerDelegate is first installed
                                    // to prevent inadvertent communication with the real
                                    // ConnectivityManager.
                                    @Override
                                    int getApplicationState() {
                                        return ApplicationState.HAS_PAUSED_ACTIVITIES;
                                    }
                                });
                    }
                };
        FutureTask<NetworkChangeNotifierAutoDetect> task = new FutureTask<>(callable);
        ThreadUtils.postOnUiThread(task);
        NetworkChangeNotifierAutoDetect ncn = task.get();

        // Insert mock ConnectivityDelegate
        mConnectivityDelegate = new MockConnectivityManagerDelegate();
        ncn.setConnectivityManagerDelegateForTests(mConnectivityDelegate);
        // Now that mock ConnectivityDelegate is inserted, pretend app is foregrounded
        // so NetworkChangeNotifierAutoDetect will register its NetworkCallback.
        Assert.assertFalse(ncn.isReceiverRegisteredForTesting());

        RegistrationPolicyApplicationStatus policy =
                (RegistrationPolicyApplicationStatus) ncn.getRegistrationPolicy();
        triggerApplicationStateChange(policy, ApplicationState.HAS_RUNNING_ACTIVITIES);
        Assert.assertTrue(ncn.isReceiverRegisteredForTesting());

        // Find NetworkChangeNotifierAutoDetect's NetworkCallback, which should have been registered
        // with mConnectivityDelegate.
        NetworkCallback networkCallback = mConnectivityDelegate.getLastRegisteredNetworkCallback();
        Assert.assertNotNull(networkCallback);

        // First thing we'll receive is a purge to initialize any network lists.
        observer.assertLastChange(ChangeType.PURGE_LIST, NetId.INVALID);

        // Test connected signal is passed along.
        mConnectivityDelegate.addNetwork(100, TRANSPORT_WIFI, false);
        observer.assertLastChange(ChangeType.CONNECT, 100);

        // Test soon-to-be-disconnected signal is passed along.
        networkCallback.onLosing(Helper.netIdToNetwork(100), 30);
        observer.assertLastChange(ChangeType.SOON_TO_DISCONNECT, 100);

        // Test connected signal is passed along.
        mConnectivityDelegate.removeNetwork(100);
        observer.assertLastChange(ChangeType.DISCONNECT, 100);

        // Simulate app backgrounding then foregrounding.
        Assert.assertTrue(ncn.isReceiverRegisteredForTesting());
        triggerApplicationStateChange(policy, ApplicationState.HAS_PAUSED_ACTIVITIES);
        Assert.assertFalse(ncn.isReceiverRegisteredForTesting());
        triggerApplicationStateChange(policy, ApplicationState.HAS_RUNNING_ACTIVITIES);
        Assert.assertTrue(ncn.isReceiverRegisteredForTesting());
        // Verify network list purged.
        observer.assertLastChange(ChangeType.PURGE_LIST, NetId.INVALID);

        //
        // VPN testing
        //

        // Add a couple normal networks
        mConnectivityDelegate.addNetwork(100, TRANSPORT_WIFI, false);
        observer.assertLastChange(ChangeType.CONNECT, 100);
        mConnectivityDelegate.addNetwork(101, TRANSPORT_CELLULAR, false);
        observer.assertLastChange(ChangeType.CONNECT, 101);

        // Verify inaccessible VPN is ignored
        mConnectivityDelegate.addNetwork(102, TRANSPORT_VPN, false);
        NetworkChangeNotifierTestUtil.flushUiThreadTaskQueue();
        Assert.assertEquals(observer.mChanges.size(), 0);
        // The disconnect will be ignored in
        // NetworkChangeNotifierDelegateAndroid::NotifyOfNetworkDisconnect() because no
        // connect event was witnessed, but it will be sent to {@code observer}
        mConnectivityDelegate.removeNetwork(102);
        observer.assertLastChange(ChangeType.DISCONNECT, 102);

        // Verify when an accessible VPN connects, all other network disconnect
        mConnectivityDelegate.addNetwork(103, TRANSPORT_VPN, true);
        NetworkChangeNotifierTestUtil.flushUiThreadTaskQueue();
        Assert.assertEquals(2, observer.mChanges.size());
        Assert.assertEquals(ChangeType.CONNECT, observer.mChanges.get(0).mChangeType);
        Assert.assertEquals(103, observer.mChanges.get(0).mNetId);
        Assert.assertEquals(ChangeType.PURGE_LIST, observer.mChanges.get(1).mChangeType);
        Assert.assertEquals(103, observer.mChanges.get(1).mNetId);
        observer.mChanges.clear();

        // Verify when an accessible VPN disconnects, all other networks reconnect
        mConnectivityDelegate.removeNetwork(103);
        NetworkChangeNotifierTestUtil.flushUiThreadTaskQueue();
        Assert.assertEquals(3, observer.mChanges.size());
        Assert.assertEquals(ChangeType.DISCONNECT, observer.mChanges.get(0).mChangeType);
        Assert.assertEquals(103, observer.mChanges.get(0).mNetId);
        Assert.assertEquals(ChangeType.CONNECT, observer.mChanges.get(1).mChangeType);
        Assert.assertEquals(100, observer.mChanges.get(1).mNetId);
        Assert.assertEquals(ChangeType.CONNECT, observer.mChanges.get(2).mChangeType);
        Assert.assertEquals(101, observer.mChanges.get(2).mNetId);
    }

    /**
     * Tests that isOnline() returns the correct result.
     */
    @Test
    @UiThreadTest
    @MediumTest
    @Feature({"Android-AppBase"})
    public void testNetworkChangeNotifierIsOnline() {
        mReceiver.register();
        Intent intent = new Intent(ConnectivityManager.CONNECTIVITY_ACTION);
        // For any connection type it should return true.
        for (int i = ConnectivityManager.TYPE_MOBILE; i < ConnectivityManager.TYPE_VPN; i++) {
            mConnectivityDelegate.setActiveNetworkExists(true);
            mConnectivityDelegate.setNetworkType(i);
            mReceiver.onReceive(InstrumentationRegistry.getTargetContext(), intent);
            Assert.assertTrue(NetworkChangeNotifier.isOnline());
        }
        mConnectivityDelegate.setActiveNetworkExists(false);
        mReceiver.onReceive(InstrumentationRegistry.getTargetContext(), intent);
        Assert.assertFalse(NetworkChangeNotifier.isOnline());
    }

    /**
     * Tests NetworkChangeNotifier.isProcessBoundToNetwork().
     */
    @Test
    @MediumTest
    @Feature({"Android-AppBase"})
    @MinAndroidSdkLevel(Build.VERSION_CODES.M)
    public void testIsProcessBoundToNetwork() throws Exception {
        ConnectivityManager connectivityManager =
                (ConnectivityManager) InstrumentationRegistry.getTargetContext().getSystemService(
                        Context.CONNECTIVITY_SERVICE);
        Network network = connectivityManager.getActiveNetwork();
        Assert.assertFalse(NetworkChangeNotifier.isProcessBoundToNetwork());
        if (network != null) {
            ConnectivityManager.setProcessDefaultNetwork(network);
            Assert.assertTrue(NetworkChangeNotifier.isProcessBoundToNetwork());
        }
        ConnectivityManager.setProcessDefaultNetwork(null);
        Assert.assertFalse(NetworkChangeNotifier.isProcessBoundToNetwork());
    }

    /**
     * Regression test for crbug.com/805424 where ConnectivityManagerDelegate.vpnAccessible() was
     * found to leak.
     */
    @Test
    @MediumTest
    @MinAndroidSdkLevel(Build.VERSION_CODES.LOLLIPOP)
    public void testVpnAccessibleDoesNotLeak() {
        ConnectivityManagerDelegate connectivityManagerDelegate = new ConnectivityManagerDelegate(
                InstrumentationRegistry.getInstrumentation().getTargetContext());
        StrictMode.VmPolicy oldPolicy = StrictMode.getVmPolicy();
        StrictMode.setVmPolicy(new StrictMode.VmPolicy.Builder()
                                       .detectLeakedClosableObjects()
                                       .penaltyDeath()
                                       .penaltyLog()
                                       .build());
        try {
            // Test non-existent Network (NetIds only go to 65535).
            connectivityManagerDelegate.vpnAccessible(Helper.netIdToNetwork(65537));
            // Test existing Networks.
            for (Network network : connectivityManagerDelegate.getAllNetworksUnfiltered()) {
                connectivityManagerDelegate.vpnAccessible(network);
            }

            // Run GC and finalizers a few times to pick up leaked closeables
            for (int i = 0; i < 10; i++) {
                System.gc();
                System.runFinalization();
            }
            System.gc();
            System.runFinalization();
        } finally {
            StrictMode.setVmPolicy(oldPolicy);
        }
    }
}
