/*
 *  Copyright 2015 The WebRTC project authors. All Rights Reserved.
 *
 *  Use of this source code is governed by a BSD-style license
 *  that can be found in the LICENSE file in the root of the source
 *  tree. An additional intellectual property rights grant can be found
 *  in the file PATENTS.  All contributing project authors may
 *  be found in the AUTHORS file in the root of the source tree.
 */

package org.webrtc;

import android.annotation.SuppressLint;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.net.ConnectivityManager;
import android.net.ConnectivityManager.NetworkCallback;
import android.net.LinkAddress;
import android.net.LinkProperties;
import android.net.Network;
import android.net.NetworkCapabilities;
import android.net.NetworkInfo;
import android.net.NetworkRequest;
import android.net.wifi.WifiInfo;
import android.net.wifi.WifiManager;
import android.net.wifi.p2p.WifiP2pGroup;
import android.net.wifi.p2p.WifiP2pManager;
import android.os.Build;
import android.telephony.TelephonyManager;
import java.net.InetAddress;
import java.net.NetworkInterface;
import java.net.SocketException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import javax.annotation.Nullable;

/**
 * Borrowed from Chromium's
 * src/net/android/java/src/org/chromium/net/NetworkChangeNotifierAutoDetect.java
 *
 * Used by the NetworkMonitor to listen to platform changes in connectivity.
 * Note that use of this class requires that the app have the platform
 * ACCESS_NETWORK_STATE permission.
 */
public class NetworkMonitorAutoDetect extends BroadcastReceiver {
  public static enum ConnectionType {
    CONNECTION_UNKNOWN,
    CONNECTION_ETHERNET,
    CONNECTION_WIFI,
    CONNECTION_4G,
    CONNECTION_3G,
    CONNECTION_2G,
    CONNECTION_UNKNOWN_CELLULAR,
    CONNECTION_BLUETOOTH,
    CONNECTION_VPN,
    CONNECTION_NONE
  }

  public static class IPAddress {
    public final byte[] address;
    public IPAddress(byte[] address) {
      this.address = address;
    }

    @CalledByNative("IPAddress")
    private byte[] getAddress() {
      return address;
    }
  }

  /** Java version of NetworkMonitor.NetworkInformation */
  public static class NetworkInformation {
    public final String name;
    public final ConnectionType type;
    // Used to specify the underlying network type if the type is CONNECTION_VPN.
    public final ConnectionType underlyingTypeForVpn;
    public final long handle;
    public final IPAddress[] ipAddresses;
    public NetworkInformation(String name, ConnectionType type, ConnectionType underlyingTypeForVpn,
        long handle, IPAddress[] addresses) {
      this.name = name;
      this.type = type;
      this.underlyingTypeForVpn = underlyingTypeForVpn;
      this.handle = handle;
      this.ipAddresses = addresses;
    }

    @CalledByNative("NetworkInformation")
    private IPAddress[] getIpAddresses() {
      return ipAddresses;
    }

    @CalledByNative("NetworkInformation")
    private ConnectionType getConnectionType() {
      return type;
    }

    @CalledByNative("NetworkInformation")
    private ConnectionType getUnderlyingConnectionTypeForVpn() {
      return underlyingTypeForVpn;
    }

    @CalledByNative("NetworkInformation")
    private long getHandle() {
      return handle;
    }

    @CalledByNative("NetworkInformation")
    private String getName() {
      return name;
    }
  };

  static class NetworkState {
    private final boolean connected;
    // Defined from ConnectivityManager.TYPE_XXX for non-mobile; for mobile, it is
    // further divided into 2G, 3G, or 4G from the subtype.
    private final int type;
    // Defined from NetworkInfo.subtype, which is one of the TelephonyManager.NETWORK_TYPE_XXXs.
    // Will be useful to find the maximum bandwidth.
    private final int subtype;
    // When the type is TYPE_VPN, the following two fields specify the similar type and subtype as
    // above for the underlying network that is used by the VPN.
    private final int underlyingNetworkTypeForVpn;
    private final int underlyingNetworkSubtypeForVpn;

    public NetworkState(boolean connected, int type, int subtype, int underlyingNetworkTypeForVpn,
        int underlyingNetworkSubtypeForVpn) {
      this.connected = connected;
      this.type = type;
      this.subtype = subtype;
      this.underlyingNetworkTypeForVpn = underlyingNetworkTypeForVpn;
      this.underlyingNetworkSubtypeForVpn = underlyingNetworkSubtypeForVpn;
    }

    public boolean isConnected() {
      return connected;
    }

    public int getNetworkType() {
      return type;
    }

    public int getNetworkSubType() {
      return subtype;
    }

    public int getUnderlyingNetworkTypeForVpn() {
      return underlyingNetworkTypeForVpn;
    }

    public int getUnderlyingNetworkSubtypeForVpn() {
      return underlyingNetworkSubtypeForVpn;
    }
  }
  /**
   * The methods in this class get called when the network changes if the callback
   * is registered with a proper network request. It is only available in Android Lollipop
   * and above.
   */
  @SuppressLint("NewApi")
  private class SimpleNetworkCallback extends NetworkCallback {
    @Override
    public void onAvailable(Network network) {
      Logging.d(TAG, "Network becomes available: " + network.toString());
      onNetworkChanged(network);
    }

    @Override
    public void onCapabilitiesChanged(Network network, NetworkCapabilities networkCapabilities) {
      // A capabilities change may indicate the ConnectionType has changed,
      // so forward the new NetworkInformation along to the observer.
      Logging.d(TAG, "capabilities changed: " + networkCapabilities.toString());
      onNetworkChanged(network);
    }

    @Override
    public void onLinkPropertiesChanged(Network network, LinkProperties linkProperties) {
      // A link property change may indicate the IP address changes.
      // so forward the new NetworkInformation to the observer.
      Logging.d(TAG, "link properties changed: " + linkProperties.toString());
      onNetworkChanged(network);
    }

    @Override
    public void onLosing(Network network, int maxMsToLive) {
      // Tell the network is going to lose in MaxMsToLive milliseconds.
      // We may use this signal later.
      Logging.d(
          TAG, "Network " + network.toString() + " is about to lose in " + maxMsToLive + "ms");
    }

    @Override
    public void onLost(Network network) {
      Logging.d(TAG, "Network " + network.toString() + " is disconnected");
      observer.onNetworkDisconnect(networkToNetId(network));
    }

    private void onNetworkChanged(Network network) {
      NetworkInformation networkInformation = connectivityManagerDelegate.networkToInfo(network);
      if (networkInformation != null) {
        observer.onNetworkConnect(networkInformation);
      }
    }
  }

  /** Queries the ConnectivityManager for information about the current connection. */
  static class ConnectivityManagerDelegate {
    /**
     *  Note: In some rare Android systems connectivityManager is null.  We handle that
     *  gracefully below.
     */
    @Nullable private final ConnectivityManager connectivityManager;

    ConnectivityManagerDelegate(Context context) {
      connectivityManager =
          (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
    }

    // For testing.
    ConnectivityManagerDelegate() {
      // All the methods below should be overridden.
      connectivityManager = null;
    }

    /**
     * Returns connection type and status information about the current
     * default network.
     */
    NetworkState getNetworkState() {
      if (connectivityManager == null) {
        return new NetworkState(false, -1, -1, -1, -1);
      }
      return getNetworkState(connectivityManager.getActiveNetworkInfo());
    }

    /**
     * Returns connection type and status information about |network|.
     * Only callable on Lollipop and newer releases.
     */
    @SuppressLint("NewApi")
    NetworkState getNetworkState(@Nullable Network network) {
      if (network == null || connectivityManager == null) {
        return new NetworkState(false, -1, -1, -1, -1);
      }
      NetworkInfo networkInfo = connectivityManager.getNetworkInfo(network);
      if (networkInfo == null) {
        Logging.w(TAG, "Couldn't retrieve information from network " + network.toString());
        return new NetworkState(false, -1, -1, -1, -1);
      }
      // The general logic of handling a VPN in this method is as follows. getNetworkInfo will
      // return the info of the network with the same id as in |network| when it is registered via
      // ConnectivityManager.registerNetworkAgent in Android. |networkInfo| may or may not indicate
      // the type TYPE_VPN if |network| is a VPN. To reliably detect the VPN interface, we need to
      // query the network capability as below in the case when networkInfo.getType() is not
      // TYPE_VPN. On the other hand when networkInfo.getType() is TYPE_VPN, the only solution so
      // far to obtain the underlying network information is to query the active network interface.
      // However, the active network interface may not be used for the VPN, for example, if the VPN
      // is restricted to WiFi by the implementation but the WiFi interface is currently turned
      // off and the active interface is the Cell. Using directly the result from
      // getActiveNetworkInfo may thus give the wrong interface information, and one should note
      // that getActiveNetworkInfo would return the default network interface if the VPN does not
      // specify its underlying networks in the implementation. Therefore, we need further compare
      // |network| to the active network. If they are not the same network, we will have to fall
      // back to report an unknown network.

      if (networkInfo.getType() != ConnectivityManager.TYPE_VPN) {
        // Note that getNetworkCapabilities returns null if the network is unknown.
        NetworkCapabilities networkCapabilities =
            connectivityManager.getNetworkCapabilities(network);
        if (networkCapabilities == null
            || !networkCapabilities.hasTransport(NetworkCapabilities.TRANSPORT_VPN)) {
          return getNetworkState(networkInfo);
        }
        // When |network| is in fact a VPN after querying its capability but |networkInfo| is not of
        // type TYPE_VPN, |networkInfo| contains the info for the underlying network, and we return
        // a NetworkState constructed from it.
        return new NetworkState(networkInfo.isConnected(), ConnectivityManager.TYPE_VPN, -1,
            networkInfo.getType(), networkInfo.getSubtype());
      }

      // When |networkInfo| is of type TYPE_VPN, which implies |network| is a VPN, we return the
      // NetworkState of the active network via getActiveNetworkInfo(), if |network| is the active
      // network that supports the VPN. Otherwise, NetworkState of an unknown network with type -1
      // will be returned.
      //
      // Note that getActiveNetwork and getActiveNetworkInfo return null if no default network is
      // currently active.
      if (networkInfo.getType() == ConnectivityManager.TYPE_VPN) {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M
            && network.equals(connectivityManager.getActiveNetwork())) {
          // If a VPN network is in place, we can find the underlying network type via querying the
          // active network info thanks to
          // https://android.googlesource.com/platform/frameworks/base/+/d6a7980d
          NetworkInfo underlyingActiveNetworkInfo = connectivityManager.getActiveNetworkInfo();
          // We use the NetworkInfo of the underlying network if it is not of TYPE_VPN itself.
          if (underlyingActiveNetworkInfo.getType() != ConnectivityManager.TYPE_VPN) {
            return new NetworkState(networkInfo.isConnected(), ConnectivityManager.TYPE_VPN, -1,
                underlyingActiveNetworkInfo.getType(), underlyingActiveNetworkInfo.getSubtype());
          }
        }
        return new NetworkState(
            networkInfo.isConnected(), ConnectivityManager.TYPE_VPN, -1, -1, -1);
      }

      return getNetworkState(networkInfo);
    }

    /**
     * Returns connection type and status information gleaned from networkInfo. Note that to obtain
     * the complete information about a VPN including the type of the underlying network, one should
     * use the above method getNetworkState with a Network object.
     */
    private NetworkState getNetworkState(@Nullable NetworkInfo networkInfo) {
      if (networkInfo == null || !networkInfo.isConnected()) {
        return new NetworkState(false, -1, -1, -1, -1);
      }
      return new NetworkState(true, networkInfo.getType(), networkInfo.getSubtype(), -1, -1);
    }

    /**
     * Returns all connected networks.
     * Only callable on Lollipop and newer releases.
     */
    @SuppressLint("NewApi")
    Network[] getAllNetworks() {
      if (connectivityManager == null) {
        return new Network[0];
      }
      return connectivityManager.getAllNetworks();
    }

    @Nullable
    List<NetworkInformation> getActiveNetworkList() {
      if (!supportNetworkCallback()) {
        return null;
      }
      ArrayList<NetworkInformation> netInfoList = new ArrayList<NetworkInformation>();
      for (Network network : getAllNetworks()) {
        NetworkInformation info = networkToInfo(network);
        if (info != null) {
          netInfoList.add(info);
        }
      }
      return netInfoList;
    }

    /**
     * Returns the NetID of the current default network. Returns
     * INVALID_NET_ID if no current default network connected.
     * Only callable on Lollipop and newer releases.
     */
    @SuppressLint("NewApi")
    long getDefaultNetId() {
      if (!supportNetworkCallback()) {
        return INVALID_NET_ID;
      }
      // Android Lollipop had no API to get the default network; only an
      // API to return the NetworkInfo for the default network. To
      // determine the default network one can find the network with
      // type matching that of the default network.
      final NetworkInfo defaultNetworkInfo = connectivityManager.getActiveNetworkInfo();
      if (defaultNetworkInfo == null) {
        return INVALID_NET_ID;
      }
      final Network[] networks = getAllNetworks();
      long defaultNetId = INVALID_NET_ID;
      for (Network network : networks) {
        if (!hasInternetCapability(network)) {
          continue;
        }
        final NetworkInfo networkInfo = connectivityManager.getNetworkInfo(network);
        if (networkInfo != null && networkInfo.getType() == defaultNetworkInfo.getType()) {
          // There should not be multiple connected networks of the
          // same type. At least as of Android Marshmallow this is
          // not supported. If this becomes supported this assertion
          // may trigger. At that point we could consider using
          // ConnectivityManager.getDefaultNetwork() though this
          // may give confusing results with VPNs and is only
          // available with Android Marshmallow.
          if (defaultNetId != INVALID_NET_ID) {
            throw new RuntimeException(
                "Multiple connected networks of same type are not supported.");
          }
          defaultNetId = networkToNetId(network);
        }
      }
      return defaultNetId;
    }

    @SuppressLint("NewApi")
    private @Nullable NetworkInformation networkToInfo(@Nullable Network network) {
      if (network == null || connectivityManager == null) {
        return null;
      }
      LinkProperties linkProperties = connectivityManager.getLinkProperties(network);
      // getLinkProperties will return null if the network is unknown.
      if (linkProperties == null) {
        Logging.w(TAG, "Detected unknown network: " + network.toString());
        return null;
      }
      if (linkProperties.getInterfaceName() == null) {
        Logging.w(TAG, "Null interface name for network " + network.toString());
        return null;
      }

      NetworkState networkState = getNetworkState(network);
      ConnectionType connectionType = getConnectionType(networkState);
      if (connectionType == ConnectionType.CONNECTION_NONE) {
        // This may not be an error. The OS may signal a network event with connection type
        // NONE when the network disconnects.
        Logging.d(TAG, "Network " + network.toString() + " is disconnected");
        return null;
      }

      // Some android device may return a CONNECTION_UNKNOWN_CELLULAR or CONNECTION_UNKNOWN type,
      // which appears to be usable. Just log them here.
      if (connectionType == ConnectionType.CONNECTION_UNKNOWN
          || connectionType == ConnectionType.CONNECTION_UNKNOWN_CELLULAR) {
        Logging.d(TAG, "Network " + network.toString() + " connection type is " + connectionType
                + " because it has type " + networkState.getNetworkType() + " and subtype "
                + networkState.getNetworkSubType());
      }
      // ConnectionType.CONNECTION_UNKNOWN if the network is not a VPN or the underlying network is
      // unknown.
      ConnectionType underlyingConnectionTypeForVpn =
          getUnderlyingConnectionTypeForVpn(networkState);

      NetworkInformation networkInformation = new NetworkInformation(
          linkProperties.getInterfaceName(), connectionType, underlyingConnectionTypeForVpn,
          networkToNetId(network), getIPAddresses(linkProperties));
      return networkInformation;
    }

    /**
     * Returns true if {@code network} can provide Internet access. Can be used to
     * ignore specialized networks (e.g. IMS, FOTA).
     */
    @SuppressLint("NewApi")
    boolean hasInternetCapability(Network network) {
      if (connectivityManager == null) {
        return false;
      }
      final NetworkCapabilities capabilities = connectivityManager.getNetworkCapabilities(network);
      return capabilities != null
          && capabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET);
    }

    /** Only callable on Lollipop and newer releases. */
    @SuppressLint("NewApi")
    public void registerNetworkCallback(NetworkCallback networkCallback) {
      connectivityManager.registerNetworkCallback(
          new NetworkRequest.Builder()
              .addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)
              .build(),
          networkCallback);
    }

    /** Only callable on Lollipop and newer releases. */
    @SuppressLint("NewApi")
    public void requestMobileNetwork(NetworkCallback networkCallback) {
      NetworkRequest.Builder builder = new NetworkRequest.Builder();
      builder.addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)
          .addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR);
      connectivityManager.requestNetwork(builder.build(), networkCallback);
    }

    @SuppressLint("NewApi")
    IPAddress[] getIPAddresses(LinkProperties linkProperties) {
      IPAddress[] ipAddresses = new IPAddress[linkProperties.getLinkAddresses().size()];
      int i = 0;
      for (LinkAddress linkAddress : linkProperties.getLinkAddresses()) {
        ipAddresses[i] = new IPAddress(linkAddress.getAddress().getAddress());
        ++i;
      }
      return ipAddresses;
    }

    @SuppressLint("NewApi")
    public void releaseCallback(NetworkCallback networkCallback) {
      if (supportNetworkCallback()) {
        Logging.d(TAG, "Unregister network callback");
        connectivityManager.unregisterNetworkCallback(networkCallback);
      }
    }

    public boolean supportNetworkCallback() {
      return Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP && connectivityManager != null;
    }
  }

  /** Queries the WifiManager for SSID of the current Wifi connection. */
  static class WifiManagerDelegate {
    @Nullable private final Context context;
    WifiManagerDelegate(Context context) {
      this.context = context;
    }

    // For testing.
    WifiManagerDelegate() {
      // All the methods below should be overridden.
      context = null;
    }

    String getWifiSSID() {
      final Intent intent = context.registerReceiver(
          null, new IntentFilter(WifiManager.NETWORK_STATE_CHANGED_ACTION));
      if (intent != null) {
        final WifiInfo wifiInfo = intent.getParcelableExtra(WifiManager.EXTRA_WIFI_INFO);
        if (wifiInfo != null) {
          final String ssid = wifiInfo.getSSID();
          if (ssid != null) {
            return ssid;
          }
        }
      }
      return "";
    }
  }

  /** Maintains the information about wifi direct (aka WifiP2p) networks. */
  static class WifiDirectManagerDelegate extends BroadcastReceiver {
    // Network "handle" for the Wifi P2p network. We have to bind to the default network id
    // (NETWORK_UNSPECIFIED) for these addresses.
    private static final int WIFI_P2P_NETWORK_HANDLE = 0;
    private final Context context;
    private final Observer observer;
    // Network information about a WifiP2p (aka WiFi-Direct) network, or null if no such network is
    // connected.
    @Nullable private NetworkInformation wifiP2pNetworkInfo;

    WifiDirectManagerDelegate(Observer observer, Context context) {
      this.context = context;
      this.observer = observer;
      IntentFilter intentFilter = new IntentFilter();
      intentFilter.addAction(WifiP2pManager.WIFI_P2P_STATE_CHANGED_ACTION);
      intentFilter.addAction(WifiP2pManager.WIFI_P2P_CONNECTION_CHANGED_ACTION);
      context.registerReceiver(this, intentFilter);
    }

    // BroadcastReceiver
    @Override
    @SuppressLint("InlinedApi")
    public void onReceive(Context context, Intent intent) {
      if (WifiP2pManager.WIFI_P2P_CONNECTION_CHANGED_ACTION.equals(intent.getAction())) {
        WifiP2pGroup wifiP2pGroup = intent.getParcelableExtra(WifiP2pManager.EXTRA_WIFI_P2P_GROUP);
        onWifiP2pGroupChange(wifiP2pGroup);
      } else if (WifiP2pManager.WIFI_P2P_STATE_CHANGED_ACTION.equals(intent.getAction())) {
        int state = intent.getIntExtra(WifiP2pManager.EXTRA_WIFI_STATE, 0 /* default to unknown */);
        onWifiP2pStateChange(state);
      }
    }

    /** Releases the broadcast receiver. */
    public void release() {
      context.unregisterReceiver(this);
    }

    public List<NetworkInformation> getActiveNetworkList() {
      if (wifiP2pNetworkInfo != null) {
        return Collections.singletonList(wifiP2pNetworkInfo);
      }

      return Collections.emptyList();
    }

    /** Handle a change notification about the wifi p2p group. */
    private void onWifiP2pGroupChange(@Nullable WifiP2pGroup wifiP2pGroup) {
      if (wifiP2pGroup == null || wifiP2pGroup.getInterface() == null) {
        return;
      }

      NetworkInterface wifiP2pInterface;
      try {
        wifiP2pInterface = NetworkInterface.getByName(wifiP2pGroup.getInterface());
      } catch (SocketException e) {
        Logging.e(TAG, "Unable to get WifiP2p network interface", e);
        return;
      }

      List<InetAddress> interfaceAddresses = Collections.list(wifiP2pInterface.getInetAddresses());
      IPAddress[] ipAddresses = new IPAddress[interfaceAddresses.size()];
      for (int i = 0; i < interfaceAddresses.size(); ++i) {
        ipAddresses[i] = new IPAddress(interfaceAddresses.get(i).getAddress());
      }

      wifiP2pNetworkInfo =
          new NetworkInformation(wifiP2pGroup.getInterface(), ConnectionType.CONNECTION_WIFI,
              ConnectionType.CONNECTION_NONE, WIFI_P2P_NETWORK_HANDLE, ipAddresses);
      observer.onNetworkConnect(wifiP2pNetworkInfo);
    }

    /** Handle a state change notification about wifi p2p. */
    private void onWifiP2pStateChange(int state) {
      if (state == WifiP2pManager.WIFI_P2P_STATE_DISABLED) {
        wifiP2pNetworkInfo = null;
        observer.onNetworkDisconnect(WIFI_P2P_NETWORK_HANDLE);
      }
    }
  }

  static final long INVALID_NET_ID = -1;
  private static final String TAG = "NetworkMonitorAutoDetect";

  // Observer for the connection type change.
  private final Observer observer;
  private final IntentFilter intentFilter;
  private final Context context;
  // Used to request mobile network. It does not do anything except for keeping
  // the callback for releasing the request.
  @Nullable private final NetworkCallback mobileNetworkCallback;
  // Used to receive updates on all networks.
  @Nullable private final NetworkCallback allNetworkCallback;
  // connectivityManagerDelegate and wifiManagerDelegate are only non-final for testing.
  private ConnectivityManagerDelegate connectivityManagerDelegate;
  private WifiManagerDelegate wifiManagerDelegate;
  private WifiDirectManagerDelegate wifiDirectManagerDelegate;

  private boolean isRegistered;
  private ConnectionType connectionType;
  private String wifiSSID;

  /**
   * Observer interface by which observer is notified of network changes.
   */
  public static interface Observer {
    /**
     * Called when default network changes.
     */
    public void onConnectionTypeChanged(ConnectionType newConnectionType);
    public void onNetworkConnect(NetworkInformation networkInfo);
    public void onNetworkDisconnect(long networkHandle);
  }

  /**
   * Constructs a NetworkMonitorAutoDetect. Should only be called on UI thread.
   */
  @SuppressLint("NewApi")
  public NetworkMonitorAutoDetect(Observer observer, Context context) {
    this.observer = observer;
    this.context = context;
    connectivityManagerDelegate = new ConnectivityManagerDelegate(context);
    wifiManagerDelegate = new WifiManagerDelegate(context);

    final NetworkState networkState = connectivityManagerDelegate.getNetworkState();
    connectionType = getConnectionType(networkState);
    wifiSSID = getWifiSSID(networkState);
    intentFilter = new IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION);

    if (PeerConnectionFactory.fieldTrialsFindFullName("IncludeWifiDirect").equals("Enabled")) {
      wifiDirectManagerDelegate = new WifiDirectManagerDelegate(observer, context);
    }

    registerReceiver();
    if (connectivityManagerDelegate.supportNetworkCallback()) {
      // On Android 6.0.0, the WRITE_SETTINGS permission is necessary for
      // requestNetwork, so it will fail. This was fixed in Android 6.0.1.
      NetworkCallback tempNetworkCallback = new NetworkCallback();
      try {
        connectivityManagerDelegate.requestMobileNetwork(tempNetworkCallback);
      } catch (java.lang.SecurityException e) {
        Logging.w(TAG, "Unable to obtain permission to request a cellular network.");
        tempNetworkCallback = null;
      }
      mobileNetworkCallback = tempNetworkCallback;
      allNetworkCallback = new SimpleNetworkCallback();
      connectivityManagerDelegate.registerNetworkCallback(allNetworkCallback);
    } else {
      mobileNetworkCallback = null;
      allNetworkCallback = null;
    }
  }

  public boolean supportNetworkCallback() {
    return connectivityManagerDelegate.supportNetworkCallback();
  }

  /**
   * Allows overriding the ConnectivityManagerDelegate for tests.
   */
  void setConnectivityManagerDelegateForTests(ConnectivityManagerDelegate delegate) {
    connectivityManagerDelegate = delegate;
  }

  /**
   * Allows overriding the WifiManagerDelegate for tests.
   */
  void setWifiManagerDelegateForTests(WifiManagerDelegate delegate) {
    wifiManagerDelegate = delegate;
  }

  /**
   * Returns whether the object has registered to receive network connectivity intents.
   * Visible for testing.
   */
  boolean isReceiverRegisteredForTesting() {
    return isRegistered;
  }

  @Nullable
  List<NetworkInformation> getActiveNetworkList() {
    List<NetworkInformation> connectivityManagerList =
        connectivityManagerDelegate.getActiveNetworkList();
    if (connectivityManagerList == null) {
      return null;
    }
    ArrayList<NetworkInformation> result =
        new ArrayList<NetworkInformation>(connectivityManagerList);
    if (wifiDirectManagerDelegate != null) {
      result.addAll(wifiDirectManagerDelegate.getActiveNetworkList());
    }
    return result;
  }

  public void destroy() {
    if (allNetworkCallback != null) {
      connectivityManagerDelegate.releaseCallback(allNetworkCallback);
    }
    if (mobileNetworkCallback != null) {
      connectivityManagerDelegate.releaseCallback(mobileNetworkCallback);
    }
    if (wifiDirectManagerDelegate != null) {
      wifiDirectManagerDelegate.release();
    }
    unregisterReceiver();
  }

  /**
   * Registers a BroadcastReceiver in the given context.
   */
  private void registerReceiver() {
    if (isRegistered)
      return;

    isRegistered = true;
    context.registerReceiver(this, intentFilter);
  }

  /**
   * Unregisters the BroadcastReceiver in the given context.
   */
  private void unregisterReceiver() {
    if (!isRegistered)
      return;

    isRegistered = false;
    context.unregisterReceiver(this);
  }

  public NetworkState getCurrentNetworkState() {
    return connectivityManagerDelegate.getNetworkState();
  }

  /**
   * Returns NetID of device's current default connected network used for
   * communication.
   * Only implemented on Lollipop and newer releases, returns INVALID_NET_ID
   * when not implemented.
   */
  public long getDefaultNetId() {
    return connectivityManagerDelegate.getDefaultNetId();
  }

  private static ConnectionType getConnectionType(
      boolean isConnected, int networkType, int networkSubtype) {
    if (!isConnected) {
      return ConnectionType.CONNECTION_NONE;
    }

    switch (networkType) {
      case ConnectivityManager.TYPE_ETHERNET:
        return ConnectionType.CONNECTION_ETHERNET;
      case ConnectivityManager.TYPE_WIFI:
        return ConnectionType.CONNECTION_WIFI;
      case ConnectivityManager.TYPE_WIMAX:
        return ConnectionType.CONNECTION_4G;
      case ConnectivityManager.TYPE_BLUETOOTH:
        return ConnectionType.CONNECTION_BLUETOOTH;
      case ConnectivityManager.TYPE_MOBILE:
        // Use information from TelephonyManager to classify the connection.
        switch (networkSubtype) {
          case TelephonyManager.NETWORK_TYPE_GPRS:
          case TelephonyManager.NETWORK_TYPE_EDGE:
          case TelephonyManager.NETWORK_TYPE_CDMA:
          case TelephonyManager.NETWORK_TYPE_1xRTT:
          case TelephonyManager.NETWORK_TYPE_IDEN:
            return ConnectionType.CONNECTION_2G;
          case TelephonyManager.NETWORK_TYPE_UMTS:
          case TelephonyManager.NETWORK_TYPE_EVDO_0:
          case TelephonyManager.NETWORK_TYPE_EVDO_A:
          case TelephonyManager.NETWORK_TYPE_HSDPA:
          case TelephonyManager.NETWORK_TYPE_HSUPA:
          case TelephonyManager.NETWORK_TYPE_HSPA:
          case TelephonyManager.NETWORK_TYPE_EVDO_B:
          case TelephonyManager.NETWORK_TYPE_EHRPD:
          case TelephonyManager.NETWORK_TYPE_HSPAP:
            return ConnectionType.CONNECTION_3G;
          case TelephonyManager.NETWORK_TYPE_LTE:
            return ConnectionType.CONNECTION_4G;
          default:
            return ConnectionType.CONNECTION_UNKNOWN_CELLULAR;
        }
      case ConnectivityManager.TYPE_VPN:
        return ConnectionType.CONNECTION_VPN;
      default:
        return ConnectionType.CONNECTION_UNKNOWN;
    }
  }

  public static ConnectionType getConnectionType(NetworkState networkState) {
    return getConnectionType(networkState.isConnected(), networkState.getNetworkType(),
        networkState.getNetworkSubType());
  }

  private static ConnectionType getUnderlyingConnectionTypeForVpn(NetworkState networkState) {
    if (networkState.getNetworkType() != ConnectivityManager.TYPE_VPN) {
      return ConnectionType.CONNECTION_NONE;
    }
    return getConnectionType(networkState.isConnected(),
        networkState.getUnderlyingNetworkTypeForVpn(),
        networkState.getUnderlyingNetworkSubtypeForVpn());
  }

  private String getWifiSSID(NetworkState networkState) {
    if (getConnectionType(networkState) != ConnectionType.CONNECTION_WIFI)
      return "";
    return wifiManagerDelegate.getWifiSSID();
  }

  // BroadcastReceiver
  @Override
  public void onReceive(Context context, Intent intent) {
    final NetworkState networkState = getCurrentNetworkState();
    if (ConnectivityManager.CONNECTIVITY_ACTION.equals(intent.getAction())) {
      connectionTypeChanged(networkState);
    }
  }

  private void connectionTypeChanged(NetworkState networkState) {
    ConnectionType newConnectionType = getConnectionType(networkState);
    String newWifiSSID = getWifiSSID(networkState);
    if (newConnectionType == connectionType && newWifiSSID.equals(wifiSSID))
      return;

    connectionType = newConnectionType;
    wifiSSID = newWifiSSID;
    Logging.d(TAG, "Network connectivity changed, type is: " + connectionType);
    observer.onConnectionTypeChanged(newConnectionType);
  }

  /**
   * Extracts NetID of network on Lollipop and NetworkHandle (which is mungled
   * NetID) on Marshmallow and newer releases. Only available on Lollipop and
   * newer releases. Returns long since getNetworkHandle returns long.
   */
  @SuppressLint("NewApi")
  private static long networkToNetId(Network network) {
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
      return network.getNetworkHandle();
    }

    // NOTE(honghaiz): This depends on Android framework implementation details.
    // These details cannot change because Lollipop has been released.
    return Integer.parseInt(network.toString());
  }
}
