/*
 * Copyright (C) 2016 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.android.server.wifi.aware;

import static android.net.RouteInfo.RTN_UNICAST;

import android.content.Context;
import android.hardware.wifi.V1_0.NanDataPathChannelCfg;
import android.hardware.wifi.V1_0.NanStatusType;
import android.hardware.wifi.V1_2.NanDataPathChannelInfo;
import android.net.ConnectivityManager;
import android.net.IpPrefix;
import android.net.LinkAddress;
import android.net.LinkProperties;
import android.net.MacAddress;
import android.net.MatchAllNetworkSpecifier;
import android.net.NetworkAgent;
import android.net.NetworkAgentConfig;
import android.net.NetworkCapabilities;
import android.net.NetworkFactory;
import android.net.NetworkProvider;
import android.net.NetworkRequest;
import android.net.NetworkSpecifier;
import android.net.RouteInfo;
import android.net.wifi.aware.TlvBufferUtils;
import android.net.wifi.aware.WifiAwareAgentNetworkSpecifier;
import android.net.wifi.aware.WifiAwareManager;
import android.net.wifi.aware.WifiAwareNetworkInfo;
import android.net.wifi.aware.WifiAwareNetworkSpecifier;
import android.net.wifi.aware.WifiAwareUtils;
import android.net.wifi.util.HexEncoding;
import android.os.Build;
import android.os.Handler;
import android.os.Looper;
import android.text.TextUtils;
import android.util.ArrayMap;
import android.util.Log;
import android.util.Pair;

import com.android.internal.annotations.VisibleForTesting;
import com.android.server.wifi.Clock;
import com.android.server.wifi.util.NetdWrapper;
import com.android.server.wifi.util.WifiPermissionsUtil;
import com.android.server.wifi.util.WifiPermissionsWrapper;

import java.io.FileDescriptor;
import java.io.PrintWriter;
import java.net.DatagramSocket;
import java.net.Inet6Address;
import java.net.InetAddress;
import java.net.NetworkInterface;
import java.net.SocketException;
import java.net.UnknownHostException;
import java.nio.ByteOrder;
import java.util.Arrays;
import java.util.Enumeration;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.SortedSet;
import java.util.TreeSet;

/**
 * Manages Aware data-path lifetime: interface creation/deletion, data-path setup and tear-down.
 * The Aware network configuration is:
 * - transport = TRANSPORT_WIFI_AWARE
 * - capabilities = NET_CAPABILITY_NOT_VPN
 * - network specifier generated by DiscoverySession.createNetworkSpecifier(...) or
 *   WifiAwareManager.createNetworkSpecifier(...).
 */
public class WifiAwareDataPathStateManager {
    private static final String TAG = "WifiAwareDataPathStMgr";
    private static final boolean VDBG = false; // STOPSHIP if true
    private boolean mDbg = false;

    private static final String AWARE_INTERFACE_PREFIX = "aware_data";
    private static final String NETWORK_TAG = "WIFI_AWARE_FACTORY";
    private static final String AGENT_TAG_PREFIX = "WIFI_AWARE_AGENT_";
    private static final int NETWORK_FACTORY_SCORE_AVAIL = 1;
    private static final int NETWORK_FACTORY_BANDWIDTH_AVAIL = 1;
    private static final int NETWORK_FACTORY_SIGNAL_STRENGTH_AVAIL = 1;

    @VisibleForTesting
    public static final int ADDRESS_VALIDATION_RETRY_INTERVAL_MS = 1_000; // 1 second
    @VisibleForTesting
    public static final int ADDRESS_VALIDATION_TIMEOUT_MS = 5_000; // 5 seconds

    private final WifiAwareStateManager mMgr;
    private final Clock mClock;
    public NetworkInterfaceWrapper mNiWrapper = new NetworkInterfaceWrapper();
    private static final NetworkCapabilities sNetworkCapabilitiesFilter =
            makeNetworkCapabilitiesFilter();
    private final Set<String> mInterfaces = new HashSet<>();
    private final Map<WifiAwareNetworkSpecifier, AwareNetworkRequestInformation>
            mNetworkRequestsCache = new ArrayMap<>();
    private Context mContext;
    private WifiAwareMetrics mAwareMetrics;
    private WifiPermissionsUtil mWifiPermissionsUtil;
    private WifiPermissionsWrapper mPermissionsWrapper;
    private Looper mLooper;
    private Handler mHandler;
    private WifiAwareNetworkFactory mNetworkFactory;
    public NetdWrapper mNetdWrapper;

    // internal debug flag to override API check
    /* package */ boolean mAllowNdpResponderFromAnyOverride = false;

    public WifiAwareDataPathStateManager(WifiAwareStateManager mgr, Clock clock) {
        mMgr = mgr;
        mClock = clock;
    }

    private static NetworkCapabilities makeNetworkCapabilitiesFilter() {
        return new NetworkCapabilities.Builder()
                .addTransportType(NetworkCapabilities.TRANSPORT_WIFI_AWARE)
                .removeCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)
                .addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_VPN)
                .addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_METERED)
                .addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_ROAMING)
                .addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_CONGESTED)
                .addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED)
                .addCapability(NetworkCapabilities.NET_CAPABILITY_TRUSTED)
                .setNetworkSpecifier(new MatchAllNetworkSpecifier())
                .setLinkUpstreamBandwidthKbps(NETWORK_FACTORY_BANDWIDTH_AVAIL)
                .setLinkDownstreamBandwidthKbps(NETWORK_FACTORY_BANDWIDTH_AVAIL)
                .setSignalStrength(NETWORK_FACTORY_SIGNAL_STRENGTH_AVAIL)
                .build();
    }

    /**
     * Initialize the Aware data-path state manager. Specifically register the network factory with
     * connectivity service.
     */
    public void start(Context context, Looper looper, WifiAwareMetrics awareMetrics,
            WifiPermissionsUtil wifiPermissionsUtil, WifiPermissionsWrapper permissionsWrapper,
            NetdWrapper netdWrapper) {
        if (VDBG) Log.v(TAG, "start");

        mContext = context;
        mAwareMetrics = awareMetrics;
        mWifiPermissionsUtil = wifiPermissionsUtil;
        mPermissionsWrapper = permissionsWrapper;
        mNetdWrapper = netdWrapper;
        mLooper = looper;
        mHandler = new Handler(mLooper);


        mNetworkFactory = new WifiAwareNetworkFactory(looper, context, sNetworkCapabilitiesFilter);
        mNetworkFactory.setScoreFilter(NETWORK_FACTORY_SCORE_AVAIL);
        mNetworkFactory.register();
    }

    /**
     * Enable verbose logging.
     */
    public void enableVerboseLogging(boolean verbose) {
        mDbg = verbose | VDBG;
    }

    private Map.Entry<WifiAwareNetworkSpecifier, AwareNetworkRequestInformation>
                getNetworkRequestByNdpId(int ndpId) {
        for (Map.Entry<WifiAwareNetworkSpecifier, AwareNetworkRequestInformation> entry :
                mNetworkRequestsCache.entrySet()) {
            if (entry.getValue().ndpId == ndpId) {
                return entry;
            }
        }

        return null;
    }

    private Map.Entry<WifiAwareNetworkSpecifier, AwareNetworkRequestInformation>
                getNetworkRequestByCanonicalDescriptor(CanonicalConnectionInfo cci) {
        if (VDBG) Log.v(TAG, "getNetworkRequestByCanonicalDescriptor: cci=" + cci);
        for (Map.Entry<WifiAwareNetworkSpecifier, AwareNetworkRequestInformation> entry :
                mNetworkRequestsCache.entrySet()) {
            if (VDBG) {
                Log.v(TAG, "getNetworkRequestByCanonicalDescriptor: entry=" + entry.getValue()
                        + " --> cci=" + entry.getValue().getCanonicalDescriptor());
            }
            if (entry.getValue().getCanonicalDescriptor().matches(cci)) {
                return entry;
            }
        }

        return null;
    }

    /**
     * Create all Aware data-path interfaces which are possible on the device - based on the
     * capabilities of the firmware.
     */
    public void createAllInterfaces() {
        if (mDbg) Log.v(TAG, "createAllInterfaces");

        if (mMgr.getCapabilities() == null) {
            Log.e(TAG, "createAllInterfaces: capabilities aren't initialized yet!");
            return;
        }

        for (int i = 0; i < mMgr.getCapabilities().maxNdiInterfaces; ++i) {
            String name = AWARE_INTERFACE_PREFIX + i;
            if (mInterfaces.contains(name)) {
                Log.e(TAG, "createAllInterfaces(): interface already up, " + name
                        + ", possibly failed to delete - deleting/creating again to be safe");
                mMgr.deleteDataPathInterface(name);

                // critical to remove so that don't get infinite loop if the delete fails again
                mInterfaces.remove(name);
            }

            mMgr.createDataPathInterface(name);
        }
    }

    /**
     * Delete all Aware data-path interfaces which are currently up.
     */
    public void deleteAllInterfaces() {
        if (mDbg) Log.v(TAG, "deleteAllInterfaces");
        onAwareDownCleanupDataPaths();

        if (mMgr.getCapabilities() == null) {
            Log.e(TAG, "deleteAllInterfaces: capabilities aren't initialized yet!");
            return;
        }

        for (int i = 0; i < mMgr.getCapabilities().maxNdiInterfaces; ++i) {
            String name = AWARE_INTERFACE_PREFIX + i;
            mMgr.deleteDataPathInterface(name);
        }
        mMgr.releaseAwareInterface();
    }

    /**
     * Called when firmware indicates the an interface was created.
     */
    public void onInterfaceCreated(String interfaceName) {
        if (mDbg) Log.v(TAG, "onInterfaceCreated: interfaceName=" + interfaceName);

        if (mInterfaces.contains(interfaceName)) {
            Log.w(TAG, "onInterfaceCreated: already contains interface -- " + interfaceName);
        }

        mInterfaces.add(interfaceName);
    }

    /**
     * Called when firmware indicates the an interface was deleted.
     */
    public void onInterfaceDeleted(String interfaceName) {
        if (mDbg) Log.v(TAG, "onInterfaceDeleted: interfaceName=" + interfaceName);

        if (!mInterfaces.contains(interfaceName)) {
            Log.w(TAG, "onInterfaceDeleted: interface not on list -- " + interfaceName);
        }

        mInterfaces.remove(interfaceName);
    }

    /**
     * Response to initiating data-path request. Indicates that request is successful (not
     * complete!) and is now in progress.
     *
     * @param networkSpecifier The network specifier provided as part of the initiate request.
     * @param ndpId            The ID assigned to the data-path.
     */
    public void onDataPathInitiateSuccess(WifiAwareNetworkSpecifier networkSpecifier, int ndpId) {
        if (mDbg) {
            Log.v(TAG,
                    "onDataPathInitiateSuccess: networkSpecifier=" + networkSpecifier + ", ndpId="
                            + ndpId);
        }

        AwareNetworkRequestInformation nnri = mNetworkRequestsCache.get(networkSpecifier);
        if (nnri == null) {
            Log.w(TAG, "onDataPathInitiateSuccess: network request not found for networkSpecifier="
                    + networkSpecifier);
            mMgr.endDataPath(ndpId);
            return;
        }

        if (nnri.state
                != AwareNetworkRequestInformation.STATE_INITIATOR_WAIT_FOR_REQUEST_RESPONSE) {
            Log.w(TAG, "onDataPathInitiateSuccess: network request in incorrect state: state="
                    + nnri.state);
            mNetworkRequestsCache.remove(networkSpecifier);
            declareUnfullfillableAndEndDp(nnri, ndpId);
            return;
        }

        nnri.state = AwareNetworkRequestInformation.STATE_WAIT_FOR_CONFIRM;
        nnri.ndpId = ndpId;
    }

    /**
     * Response to an attempt to set up a data-path (on the initiator side).
     *
     * @param networkSpecifier The network specifier provided as part of the initiate request.
     * @param reason           Failure reason.
     */
    public void onDataPathInitiateFail(WifiAwareNetworkSpecifier networkSpecifier, int reason) {
        if (mDbg) {
            Log.v(TAG,
                    "onDataPathInitiateFail: networkSpecifier=" + networkSpecifier + ", reason="
                            + reason);
        }

        AwareNetworkRequestInformation nnri = mNetworkRequestsCache.remove(networkSpecifier);
        if (nnri == null) {
            Log.w(TAG, "onDataPathInitiateFail: network request not found for networkSpecifier="
                    + networkSpecifier);
            return;
        }
        mNetworkFactory.letAppKnowThatRequestsAreUnavailable(nnri);

        if (nnri.state
                != AwareNetworkRequestInformation.STATE_INITIATOR_WAIT_FOR_REQUEST_RESPONSE) {
            Log.w(TAG, "onDataPathInitiateFail: network request in incorrect state: state="
                    + nnri.state);
        }

        mAwareMetrics.recordNdpStatus(reason, networkSpecifier.isOutOfBand(), nnri.startTimestamp);
    }


    /**
     * Notification (unsolicited/asynchronous) that a peer has requested to set up a data-path
     * connection with us.
     *
     * @param pubSubId      The ID of the discovery session context for the data-path - or 0 if not
     *                      related to a discovery session.
     * @param mac           The discovery MAC address of the peer.
     * @param ndpId         The locally assigned ID for the data-path.
     * @param message       The app_info HAL field (peer's info: binary blob)
     * @return The network specifier of the data-path (or null if none/error)
     */
    public WifiAwareNetworkSpecifier onDataPathRequest(int pubSubId, byte[] mac, int ndpId,
            byte[] message) {
        if (mDbg) {
            Log.v(TAG,
                    "onDataPathRequest: pubSubId=" + pubSubId + ", mac=" + String.valueOf(
                            HexEncoding.encode(mac)) + ", ndpId=" + ndpId);
        }

        WifiAwareNetworkSpecifier networkSpecifier = null;
        AwareNetworkRequestInformation nnri = null;
        for (Map.Entry<WifiAwareNetworkSpecifier, AwareNetworkRequestInformation> entry :
                mNetworkRequestsCache.entrySet()) {
            /*
             * Checking that the incoming request (from the Initiator) matches the request
             * we (the Responder) already have set up. The rules are:
             * - The discovery session (pub/sub ID) must match.
             * - The peer MAC address (if specified - i.e. non-null) must match. A null peer MAC ==
             *   accept (otherwise matching) requests from any peer MAC.
             * - The request must be pending (i.e. we could have completed requests for the same
             *   parameters)
             */
            if (entry.getValue().pubSubId != 0 && entry.getValue().pubSubId != pubSubId) {
                continue;
            }

            if (entry.getValue().peerDiscoveryMac != null && !Arrays.equals(
                    entry.getValue().peerDiscoveryMac, mac)) {
                continue;
            }

            if (entry.getValue().state
                    != AwareNetworkRequestInformation.STATE_RESPONDER_WAIT_FOR_REQUEST) {
                continue;
            }

            networkSpecifier = entry.getKey();
            nnri = entry.getValue();
            break;
        }

        // it is also possible that this is an initiator-side data-path request indication (which
        // happens when the Responder responds). In such a case it will be matched by the NDP ID.
        Map.Entry<WifiAwareNetworkSpecifier, AwareNetworkRequestInformation> nnriE =
                getNetworkRequestByNdpId(ndpId);
        if (nnriE != null) {
            if (VDBG) {
                Log.v(TAG,
                        "onDataPathRequest: initiator-side indication for " + nnriE.getValue());
            }

            // potential transmission mechanism for port/transport-protocol information from
            // Responder (alternative to confirm message)
            NetworkInformationData.ParsedResults peerServerInfo = NetworkInformationData.parseTlv(
                    message);
            if (peerServerInfo != null) {
                if (peerServerInfo.port != 0) {
                    nnriE.getValue().peerPort = peerServerInfo.port;
                }
                if (peerServerInfo.transportProtocol != -1) {
                    nnriE.getValue().peerTransportProtocol = peerServerInfo.transportProtocol;
                }
                if (peerServerInfo.ipv6Override != null) {
                    nnriE.getValue().peerIpv6Override = peerServerInfo.ipv6Override;
                }
            }

            return null; // ignore this for NDP set up flow: it is used to obtain app_info from Resp
        }

        if (nnri == null) {
            Log.w(TAG, "onDataPathRequest: can't find a request with specified pubSubId=" + pubSubId
                    + ", mac=" + String.valueOf(HexEncoding.encode(mac)));
            if (VDBG) {
                Log.v(TAG, "onDataPathRequest: network request cache = " + mNetworkRequestsCache);
            }
            mMgr.respondToDataPathRequest(false, ndpId, "", null, null, null, false);
            return null;
        }

        if (nnri.peerDiscoveryMac == null) {
            // the "accept anyone" request is now specific
            nnri.peerDiscoveryMac = mac;
        }
        nnri.interfaceName = selectInterfaceForRequest(nnri);
        if (nnri.interfaceName == null) {
            Log.w(TAG,
                    "onDataPathRequest: request " + networkSpecifier + " no interface available");
            mMgr.respondToDataPathRequest(false, ndpId, "", null, null, null, false);
            mNetworkRequestsCache.remove(networkSpecifier);
            mNetworkFactory.letAppKnowThatRequestsAreUnavailable(nnri);
            return null;
        }

        nnri.state = AwareNetworkRequestInformation.STATE_RESPONDER_WAIT_FOR_RESPOND_RESPONSE;
        nnri.ndpId = ndpId;
        nnri.startTimestamp = mClock.getElapsedSinceBootMillis();
        mMgr.respondToDataPathRequest(true, ndpId, nnri.interfaceName, nnri.networkSpecifier.pmk,
                nnri.networkSpecifier.passphrase,
                NetworkInformationData.buildTlv(nnri.networkSpecifier.port,
                        nnri.networkSpecifier.transportProtocol),
                nnri.networkSpecifier.isOutOfBand());

        return networkSpecifier;
    }

    /**
     * Called on the RESPONDER when the response to data-path request has been completed.
     *
     * @param ndpId The ID of the data-path (NDP)
     * @param success Whether or not the 'RespondToDataPathRequest' operation was a success.
     */
    public void onRespondToDataPathRequest(int ndpId, boolean success, int reasonOnFailure) {
        if (mDbg) {
            Log.v(TAG, "onRespondToDataPathRequest: ndpId=" + ndpId + ", success=" + success);
        }

        WifiAwareNetworkSpecifier networkSpecifier = null;
        AwareNetworkRequestInformation nnri = null;
        for (Map.Entry<WifiAwareNetworkSpecifier, AwareNetworkRequestInformation> entry :
                mNetworkRequestsCache.entrySet()) {
            if (entry.getValue().ndpId == ndpId) {
                networkSpecifier = entry.getKey();
                nnri = entry.getValue();
                break;
            }
        }

        if (nnri == null) {
            Log.w(TAG, "onRespondToDataPathRequest: can't find a request with specified ndpId="
                    + ndpId);
            if (VDBG) {
                Log.v(TAG, "onRespondToDataPathRequest: network request cache = "
                        + mNetworkRequestsCache);
            }
            return;
        }

        if (!success) {
            Log.w(TAG, "onRespondToDataPathRequest: request " + networkSpecifier
                    + " failed responding");
            mMgr.endDataPath(ndpId);
            mNetworkRequestsCache.remove(networkSpecifier);
            mNetworkFactory.letAppKnowThatRequestsAreUnavailable(nnri);
            mAwareMetrics.recordNdpStatus(reasonOnFailure, networkSpecifier.isOutOfBand(),
                    nnri.startTimestamp);
            return;
        }

        if (nnri.state
                != AwareNetworkRequestInformation.STATE_RESPONDER_WAIT_FOR_RESPOND_RESPONSE) {
            Log.w(TAG, "onRespondToDataPathRequest: request " + networkSpecifier
                    + " is incorrect state=" + nnri.state);
            mMgr.endDataPath(ndpId);
            mNetworkRequestsCache.remove(networkSpecifier);
            mNetworkFactory.letAppKnowThatRequestsAreUnavailable(nnri);
            return;
        }

        nnri.state = AwareNetworkRequestInformation.STATE_WAIT_FOR_CONFIRM;
    }

    /**
     * Notification (unsolicited/asynchronous) that the data-path (which we've been setting up)
     * is possibly (if {@code accept} is {@code true}) ready for use from the firmware's
     * perspective - now can do L3 configuration.
     *
     * @param ndpId         Id of the data-path
     * @param mac           The MAC address of the peer's data-path (not discovery interface). Only
     *                      valid
     *                      if {@code accept} is {@code true}.
     * @param accept        Indicates whether the data-path setup has succeeded (been accepted) or
     *                      failed (been rejected).
     * @param reason        If {@code accept} is {@code false} provides a reason code for the
     *                      rejection/failure.
     * @param message       The message provided by the peer as part of the data-path setup
     *                      process.
     * @param channelInfo   Lists of channels used for this NDP.
     * @return The network specifier of the data-path or a null if none/error.
     */
    public WifiAwareNetworkSpecifier onDataPathConfirm(int ndpId, byte[] mac, boolean accept,
            int reason, byte[] message, List<NanDataPathChannelInfo> channelInfo) {
        if (mDbg) {
            Log.v(TAG, "onDataPathConfirm: ndpId=" + ndpId + ", mac=" + String.valueOf(
                    HexEncoding.encode(mac)) + ", accept=" + accept + ", reason=" + reason
                    + ", message.length=" + ((message == null) ? 0 : message.length)
                    + ", channelInfo=" + channelInfo);
        }

        Map.Entry<WifiAwareNetworkSpecifier, AwareNetworkRequestInformation> nnriE =
                getNetworkRequestByNdpId(ndpId);
        if (nnriE == null) {
            Log.w(TAG, "onDataPathConfirm: network request not found for ndpId=" + ndpId);
            if (accept) {
                mMgr.endDataPath(ndpId);
            }
            return null;
        }

        WifiAwareNetworkSpecifier networkSpecifier = nnriE.getKey();
        AwareNetworkRequestInformation nnri = nnriE.getValue();

        // validate state
        if (nnri.state != AwareNetworkRequestInformation.STATE_WAIT_FOR_CONFIRM) {
            Log.w(TAG, "onDataPathConfirm: invalid state=" + nnri.state);
            mNetworkRequestsCache.remove(networkSpecifier);
            mNetworkFactory.letAppKnowThatRequestsAreUnavailable(nnri);
            if (accept) {
                mMgr.endDataPath(ndpId);
            }
            return networkSpecifier;
        }

        if (accept) {
            nnri.state = AwareNetworkRequestInformation.STATE_CONFIRMED;
            nnri.peerDataMac = mac;
            nnri.channelInfo = channelInfo;

            if (!isInterfaceUpAndUsedByAnotherNdp(nnri)) {
                try {
                    mNetdWrapper.setInterfaceUp(nnri.interfaceName);
                    mNetdWrapper.enableIpv6(nnri.interfaceName);
                } catch (Exception e) { // NwService throws runtime exceptions for errors
                    Log.e(TAG, "onDataPathConfirm: ACCEPT nnri=" + nnri
                            + ": can't configure network - "
                            + e);
                    declareUnfullfillableAndEndDp(nnri, ndpId);
                    return networkSpecifier;
                }
            } else {
                if (VDBG) {
                    Log.v(TAG, "onDataPathConfirm: interface already configured: "
                            + nnri.interfaceName);
                }
            }

            // only relevant for the initiator
            if (nnri.networkSpecifier.role
                    == WifiAwareManager.WIFI_AWARE_DATA_PATH_ROLE_INITIATOR) {
                NetworkInformationData.ParsedResults peerServerInfo =
                        NetworkInformationData.parseTlv(message);
                if (peerServerInfo != null) {
                    if (peerServerInfo.port != 0) {
                        nnri.peerPort = peerServerInfo.port;
                    }
                    if (peerServerInfo.transportProtocol != -1) {
                        nnri.peerTransportProtocol = peerServerInfo.transportProtocol;
                    }
                    if (peerServerInfo.ipv6Override != null) {
                        nnri.peerIpv6Override = peerServerInfo.ipv6Override;
                    }
                }
            }

            nnri.startValidationTimestamp = mClock.getElapsedSinceBootMillis();
            handleAddressValidation(nnri, ndpId, networkSpecifier.isOutOfBand(), mac);
        } else {
            if (VDBG) {
                Log.v(TAG, "onDataPathConfirm: data-path for networkSpecifier=" + networkSpecifier
                        + " rejected - reason=" + reason);
            }
            mNetworkRequestsCache.remove(networkSpecifier);
            mNetworkFactory.letAppKnowThatRequestsAreUnavailable(nnri);
            mAwareMetrics.recordNdpStatus(reason, networkSpecifier.isOutOfBand(),
                    nnri.startTimestamp);
        }

        return networkSpecifier;
    }

    private void getInet6Address(AwareNetworkRequestInformation nnri, byte[] mac) {
        try {
            byte[] addr;
            if (nnri.peerIpv6Override == null) {
                addr = MacAddress.fromBytes(mac).getLinkLocalIpv6FromEui48Mac().getAddress();
            } else {
                addr = new byte[16];
                addr[0] = (byte) 0xfe;
                addr[1] = (byte) 0x80;
                addr[8] = nnri.peerIpv6Override[0];
                addr[9] = nnri.peerIpv6Override[1];
                addr[10] = nnri.peerIpv6Override[2];
                addr[11] = nnri.peerIpv6Override[3];
                addr[12] = nnri.peerIpv6Override[4];
                addr[13] = nnri.peerIpv6Override[5];
                addr[14] = nnri.peerIpv6Override[6];
                addr[15] = nnri.peerIpv6Override[7];
            }
            nnri.peerIpv6 = Inet6Address.getByAddress(null, addr,
                    NetworkInterface.getByName(nnri.interfaceName));
        } catch (SocketException | UnknownHostException e) {
            if (mDbg) {
                Log.d(TAG, "onDataPathConfirm: error obtaining scoped IPv6 address -- " + e);
            }
            nnri.peerIpv6 = null;
        }
    }

    private void handleAddressValidation(AwareNetworkRequestInformation nnri, int ndpId,
            boolean isOutOfBand, byte[] mac) {
        final NetworkCapabilities.Builder ncBuilder = new NetworkCapabilities.Builder(
                sNetworkCapabilitiesFilter);
        LinkProperties linkProperties = new LinkProperties();
        getInet6Address(nnri, mac);
        if (!(nnri.peerIpv6 != null && mNiWrapper.configureAgentProperties(nnri,
                nnri.equivalentRequests, ndpId, ncBuilder, linkProperties)
                && mNiWrapper.isAddressUsable(linkProperties))) {
            if (VDBG) {
                Log.d(TAG, "Failed address validation");
            }
            if (!isAddressValidationExpired(nnri, ndpId)) {
                mHandler.postDelayed(() -> {
                    handleAddressValidation(nnri, ndpId, isOutOfBand, mac);
                }, ADDRESS_VALIDATION_RETRY_INTERVAL_MS);
            }
            return;
        }
        final WifiAwareNetworkInfo ni = new WifiAwareNetworkInfo(
                nnri.peerIpv6, nnri.peerPort, nnri.peerTransportProtocol);
        ncBuilder.setTransportInfo(ni);
        if (VDBG) {
            Log.v(TAG, "onDataPathConfirm: AwareNetworkInfo=" + ni);
        }
        final NetworkAgentConfig naConfig = new NetworkAgentConfig.Builder()
                .setLegacyType(ConnectivityManager.TYPE_NONE)
                .setLegacyTypeName(NETWORK_TAG)
                .build();
        nnri.networkAgent = new WifiAwareNetworkAgent(mLooper, mContext,
                AGENT_TAG_PREFIX + nnri.ndpId, ncBuilder.build(), linkProperties,
                NETWORK_FACTORY_SCORE_AVAIL, naConfig, mNetworkFactory.getProvider(), nnri);
        mNiWrapper.setConnected(nnri.networkAgent);
        mAwareMetrics.recordNdpStatus(NanStatusType.SUCCESS, isOutOfBand, nnri.startTimestamp);
        nnri.startTimestamp = mClock.getElapsedSinceBootMillis(); // update time-stamp
        mAwareMetrics.recordNdpCreation(nnri.uid, nnri.packageName, mNetworkRequestsCache);
    }

    private boolean isAddressValidationExpired(AwareNetworkRequestInformation nnri, int ndpId) {
        if (mClock.getElapsedSinceBootMillis() - nnri.startValidationTimestamp
                > ADDRESS_VALIDATION_TIMEOUT_MS) {
            Log.e(TAG, "Timed-out while waiting for IPv6 address to be usable");
            mMgr.endDataPath(ndpId);
            nnri.state = AwareNetworkRequestInformation.STATE_TERMINATING;
            declareUnfullfillableAndEndDp(nnri, ndpId);
            return true;
        }
        return false;
    }

    private void declareUnfullfillableAndEndDp(AwareNetworkRequestInformation nnri, int ndpId) {
        mNetworkFactory.letAppKnowThatRequestsAreUnavailable(nnri);
        mMgr.endDataPath(ndpId);
        nnri.state = AwareNetworkRequestInformation.STATE_TERMINATING;
    }

    /**
     * Notification (unsolicited/asynchronous) from the firmware that the specified data-path has
     * been terminated.
     *
     * @param ndpId The ID of the terminated data-path.
     */
    public void onDataPathEnd(int ndpId) {
        if (mDbg) Log.v(TAG, "onDataPathEnd: ndpId=" + ndpId);

        Map.Entry<WifiAwareNetworkSpecifier, AwareNetworkRequestInformation> nnriE =
                getNetworkRequestByNdpId(ndpId);
        if (nnriE == null) {
            if (VDBG) {
                Log.v(TAG, "onDataPathEnd: network request not found for ndpId=" + ndpId);
            }
            return;
        }

        tearDownInterfaceIfPossible(nnriE.getValue());
        if (nnriE.getValue().state == AwareNetworkRequestInformation.STATE_CONFIRMED
                || nnriE.getValue().state == AwareNetworkRequestInformation.STATE_TERMINATING) {
            mAwareMetrics.recordNdpSessionDuration(nnriE.getValue().startTimestamp);
        }
        mNetworkRequestsCache.remove(nnriE.getKey());

        mNetworkFactory.tickleConnectivityIfWaiting();
    }

    /**
     * Notification (unsolicited/asynchronous) from the firmware that the channel for the specified
     * NDP ids has been updated.
     */
    public void onDataPathSchedUpdate(byte[] peerMac, List<Integer> ndpIds,
            List<NanDataPathChannelInfo> channelInfo) {
        if (mDbg) {
            Log.v(TAG, "onDataPathSchedUpdate: peerMac=" + MacAddress.fromBytes(peerMac).toString()
                    + ", ndpIds=" + ndpIds + ", channelInfo=" + channelInfo);
        }

        for (int ndpId : ndpIds) {
            Map.Entry<WifiAwareNetworkSpecifier, AwareNetworkRequestInformation> nnriE =
                    getNetworkRequestByNdpId(ndpId);
            if (nnriE == null) {
                Log.e(TAG, "onDataPathSchedUpdate: ndpId=" + ndpId + " - not found");
                continue;
            }
            if (!Arrays.equals(peerMac, nnriE.getValue().peerDiscoveryMac)) {
                Log.e(TAG, "onDataPathSchedUpdate: ndpId=" + ndpId + ", report NMI="
                        + MacAddress.fromBytes(peerMac).toString() + " doesn't match NDP NMI="
                        + MacAddress.fromBytes(nnriE.getValue().peerDiscoveryMac).toString());
                continue;
            }

            nnriE.getValue().channelInfo = channelInfo;
        }
    }

    /**
     * Called whenever Aware comes down. Clean up all pending and up network requests and agents.
     */
    public void onAwareDownCleanupDataPaths() {
        if (mDbg) Log.v(TAG, "onAwareDownCleanupDataPaths");

        Iterator<Map.Entry<WifiAwareNetworkSpecifier, AwareNetworkRequestInformation>> it =
                mNetworkRequestsCache.entrySet().iterator();
        while (it.hasNext()) {
            tearDownInterfaceIfPossible(it.next().getValue());
            it.remove();
        }
    }

    /**
     * Called when timed-out waiting for confirmation of the data-path setup (i.e.
     * onDataPathConfirm). Started on the initiator when executing the request for the data-path
     * and on the responder when received a request for data-path (in both cases only on success
     * - i.e. when we're proceeding with data-path setup).
     */
    public void handleDataPathTimeout(NetworkSpecifier networkSpecifier) {
        if (mDbg) Log.v(TAG, "handleDataPathTimeout: networkSpecifier=" + networkSpecifier);

        AwareNetworkRequestInformation nnri = mNetworkRequestsCache.remove(networkSpecifier);
        if (nnri == null) {
            if (VDBG) {
                Log.v(TAG,
                        "handleDataPathTimeout: network request not found for networkSpecifier="
                                + networkSpecifier);
            }
            return;
        }
        mAwareMetrics.recordNdpStatus(NanStatusType.INTERNAL_FAILURE,
                nnri.networkSpecifier.isOutOfBand(), nnri.startTimestamp);
        mNetworkFactory.letAppKnowThatRequestsAreUnavailable(nnri);

        mMgr.endDataPath(nnri.ndpId);
        nnri.state = AwareNetworkRequestInformation.STATE_TERMINATING;
    }

    private class WifiAwareNetworkFactory extends NetworkFactory {
        // Request received while waiting for confirmation that a canonically identical data-path
        // (NDP) is in the process of being terminated
        private boolean mWaitingForTermination = false;

        WifiAwareNetworkFactory(Looper looper, Context context, NetworkCapabilities filter) {
            super(looper, context, NETWORK_TAG, filter);
        }

        public void tickleConnectivityIfWaiting() {
            if (mWaitingForTermination) {
                if (VDBG) Log.v(TAG, "tickleConnectivityIfWaiting: was waiting!");
                mWaitingForTermination = false;
                reevaluateAllRequests();
            }
        }

        @Override
        public boolean acceptRequest(NetworkRequest request, int score) {
            if (VDBG) {
                Log.v(TAG, "WifiAwareNetworkFactory.acceptRequest: request=" + request + ", score="
                        + score);
            }

            if (!mMgr.isUsageEnabled()) {
                if (VDBG) {
                    Log.v(TAG, "WifiAwareNetworkFactory.acceptRequest: request=" + request
                            + " -- Aware disabled");
                }
                return false;
            }

            if (mInterfaces.isEmpty()) {
                Log.w(TAG, "WifiAwareNetworkFactory.acceptRequest: request=" + request
                        + " -- No Aware interfaces are up");
                return false;
            }

            NetworkSpecifier networkSpecifierBase = request.getNetworkSpecifier();
            if (!(networkSpecifierBase instanceof WifiAwareNetworkSpecifier)) {
                Log.w(TAG, "WifiAwareNetworkFactory.acceptRequest: request=" + request
                        + " - not a WifiAwareNetworkSpecifier");
                return false;
            }

            WifiAwareNetworkSpecifier networkSpecifier =
                    (WifiAwareNetworkSpecifier) networkSpecifierBase;

            // look up specifier - are we being called again?
            AwareNetworkRequestInformation nnri = mNetworkRequestsCache.get(networkSpecifier);
            if (nnri != null) {
                if (VDBG) {
                    Log.v(TAG, "WifiAwareNetworkFactory.acceptRequest: request=" + request
                            + " - already in cache with state=" + nnri.state);
                }

                if (nnri.state == AwareNetworkRequestInformation.STATE_TERMINATING) {
                    mWaitingForTermination = true;
                    return false;
                }

                // seems to happen after a network agent is created - trying to rematch all
                // requests again!?
                return true;
            }

            nnri = AwareNetworkRequestInformation.processNetworkSpecifier(request, networkSpecifier,
                    mMgr, mWifiPermissionsUtil, mPermissionsWrapper,
                    mAllowNdpResponderFromAnyOverride);
            if (nnri == null) {
                Log.e(TAG, "WifiAwareNetworkFactory.acceptRequest: request=" + request
                        + " - can't parse network specifier");
                releaseRequestAsUnfulfillableByAnyFactory(request);
                return false;
            }

            // check to see if a canonical version exists
            Map.Entry<WifiAwareNetworkSpecifier, AwareNetworkRequestInformation> primaryRequest =
                    getNetworkRequestByCanonicalDescriptor(nnri.getCanonicalDescriptor());
            if (primaryRequest != null) {
                if (VDBG) {
                    Log.v(TAG, "WifiAwareNetworkFactory.acceptRequest: request=" + request
                            + ", already has a primary request=" + primaryRequest.getKey()
                            + " with state=" + primaryRequest.getValue().state);
                }

                if (primaryRequest.getValue().state
                        == AwareNetworkRequestInformation.STATE_TERMINATING) {
                    mWaitingForTermination = true;
                } else {
                    primaryRequest.getValue().updateToSupportNewRequest(request);
                }
                return false;
            }

            mNetworkRequestsCache.put(networkSpecifier, nnri);

            return true;
        }

        @Override
        protected void needNetworkFor(NetworkRequest networkRequest, int score) {
            if (mDbg) {
                Log.v(TAG, "WifiAwareNetworkFactory.needNetworkFor: networkRequest="
                        + networkRequest + ", score=" + score);
            }

            NetworkSpecifier networkSpecifierObj = networkRequest.getNetworkSpecifier();
            WifiAwareNetworkSpecifier networkSpecifier = null;
            if (networkSpecifierObj instanceof WifiAwareNetworkSpecifier) {
                networkSpecifier = (WifiAwareNetworkSpecifier) networkSpecifierObj;
            }
            AwareNetworkRequestInformation nnri = mNetworkRequestsCache.get(networkSpecifier);
            if (nnri == null) {
                Log.e(TAG, "WifiAwareNetworkFactory.needNetworkFor: networkRequest="
                        + networkRequest + " not in cache!?");
                return;
            }

            if (nnri.state != AwareNetworkRequestInformation.STATE_IDLE) {
                if (VDBG) {
                    Log.v(TAG, "WifiAwareNetworkFactory.needNetworkFor: networkRequest="
                            + networkRequest + " - already in progress");
                    // TODO: understand how/when can be called again/while in progress (seems
                    // to be related to score re-calculation after a network agent is created)
                }
                return;
            }
            if (nnri.networkSpecifier.role
                    == WifiAwareManager.WIFI_AWARE_DATA_PATH_ROLE_INITIATOR) {
                nnri.interfaceName = selectInterfaceForRequest(nnri);
                if (nnri.interfaceName == null) {
                    Log.w(TAG, "needNetworkFor: request " + networkSpecifier
                            + " no interface available");
                    mNetworkRequestsCache.remove(networkSpecifier);
                    letAppKnowThatRequestsAreUnavailable(nnri);
                    return;
                }

                mMgr.initiateDataPathSetup(networkSpecifier, nnri.peerInstanceId,
                        NanDataPathChannelCfg.CHANNEL_NOT_REQUESTED, selectChannelForRequest(nnri),
                        nnri.peerDiscoveryMac, nnri.interfaceName, nnri.networkSpecifier.pmk,
                        nnri.networkSpecifier.passphrase, nnri.networkSpecifier.isOutOfBand(),
                        null);
                nnri.state =
                        AwareNetworkRequestInformation.STATE_INITIATOR_WAIT_FOR_REQUEST_RESPONSE;
                nnri.startTimestamp = mClock.getElapsedSinceBootMillis();
            } else {
                nnri.state = AwareNetworkRequestInformation.STATE_RESPONDER_WAIT_FOR_REQUEST;
            }
        }

        @Override
        protected void releaseNetworkFor(NetworkRequest networkRequest) {
            if (mDbg) {
                Log.v(TAG, "WifiAwareNetworkFactory.releaseNetworkFor: networkRequest="
                        + networkRequest);
            }

            NetworkSpecifier networkSpecifierObj = networkRequest.getNetworkSpecifier();
            WifiAwareNetworkSpecifier networkSpecifier = null;
            if (networkSpecifierObj instanceof WifiAwareNetworkSpecifier) {
                networkSpecifier = (WifiAwareNetworkSpecifier) networkSpecifierObj;
            }

            AwareNetworkRequestInformation nnri = mNetworkRequestsCache.get(networkSpecifier);
            if (nnri == null) {
                Log.e(TAG, "WifiAwareNetworkFactory.releaseNetworkFor: networkRequest="
                        + networkRequest + " not in cache!?");
                return;
            }

            if (nnri.networkAgent != null) {
                if (VDBG) {
                    Log.v(TAG, "WifiAwareNetworkFactory.releaseNetworkFor: networkRequest="
                            + networkRequest + ", nnri=" + nnri
                            + ": agent already created - deferring ending data-path to agent"
                            + ".unwanted()");
                }
                return;
            }

            /*
             * Since there's no agent it means we're in the process of setting up the NDP.
             * However, it is possible that there were other equivalent requests for this NDP. We
             * should keep going in that case.
             */
            nnri.removeSupportForRequest(networkRequest);
            if (nnri.equivalentRequests.isEmpty()) {
                if (mDbg) {
                    Log.v(TAG, "releaseNetworkFor: there are no further requests, networkRequest="
                            + networkRequest);
                }
                if (nnri.ndpId != 0) { // 0 is never a valid ID!
                    if (VDBG) Log.v(TAG, "releaseNetworkFor: in progress NDP being terminated");
                    mMgr.endDataPath(nnri.ndpId);
                    nnri.state = AwareNetworkRequestInformation.STATE_TERMINATING;
                } else {
                    mNetworkRequestsCache.remove(networkSpecifier);
                    if (nnri.networkAgent != null) {
                        letAppKnowThatRequestsAreUnavailable(nnri);
                    }
                }
            } else {
                if (VDBG) {
                    Log.v(TAG, "releaseNetworkFor: equivalent requests exist - not terminating "
                            + "networkRequest=" + networkRequest);
                }
            }
        }

        void letAppKnowThatRequestsAreUnavailable(AwareNetworkRequestInformation nnri) {
            for (NetworkRequest nr : nnri.equivalentRequests) {
                releaseRequestAsUnfulfillableByAnyFactory(nr);
            }
        }
    }

    /**
     * Network agent for Wi-Fi Aware.
     */
    @VisibleForTesting
    public class WifiAwareNetworkAgent extends NetworkAgent {
        private AwareNetworkRequestInformation mAwareNetworkRequestInfo;

        WifiAwareNetworkAgent(Looper looper, Context context, String logTag,
                NetworkCapabilities nc, LinkProperties lp, int score,
                NetworkAgentConfig config, NetworkProvider provider,
                AwareNetworkRequestInformation anri) {
            super(context, looper, logTag, nc, lp, score, config, provider);
            mAwareNetworkRequestInfo = anri;
            register();
        }

        @Override
        public void onNetworkUnwanted() {
            if (mDbg) {
                Log.v(TAG, "WifiAwareNetworkAgent.unwanted: request=" + mAwareNetworkRequestInfo);
            }

            mMgr.endDataPath(mAwareNetworkRequestInfo.ndpId);
            mAwareNetworkRequestInfo.state = AwareNetworkRequestInformation.STATE_TERMINATING;

            // Will get a callback (on both initiator and responder) when data-path actually
            // terminated. At that point will inform the agent and will clear the cache.
        }

        void reconfigureAgentAsDisconnected() {
            if (mDbg) {
                Log.v(TAG, "WifiAwareNetworkAgent.reconfigureAgentAsDisconnected: request="
                        + mAwareNetworkRequestInfo);
            }
            unregister();
        }
    }

    private void tearDownInterfaceIfPossible(AwareNetworkRequestInformation nnri) {
        if (VDBG) Log.v(TAG, "tearDownInterfaceIfPossible: nnri=" + nnri);

        if (!TextUtils.isEmpty(nnri.interfaceName)) {
            boolean interfaceUsedByAnotherNdp = isInterfaceUpAndUsedByAnotherNdp(nnri);
            if (interfaceUsedByAnotherNdp) {
                if (mDbg) {
                    Log.v(TAG, "tearDownInterfaceIfPossible: interfaceName=" + nnri.interfaceName
                            + ", still in use - not turning down");
                }
            } else {
                try {
                    mNetdWrapper.setInterfaceDown(nnri.interfaceName);
                } catch (Exception e) { // NwService throws runtime exceptions for errors
                    Log.e(TAG, "tearDownInterfaceIfPossible: nnri=" + nnri
                            + ": can't bring interface down - " + e);
                }
            }
        }

        if (nnri.networkAgent == null) {
            mNetworkFactory.letAppKnowThatRequestsAreUnavailable(nnri);
        } else {
            nnri.networkAgent.reconfigureAgentAsDisconnected();
        }
    }

    private boolean isInterfaceUpAndUsedByAnotherNdp(AwareNetworkRequestInformation nri) {
        for (AwareNetworkRequestInformation lnri : mNetworkRequestsCache.values()) {
            if (lnri == nri) {
                continue;
            }

            if (nri.interfaceName.equals(lnri.interfaceName) && (
                    lnri.state == AwareNetworkRequestInformation.STATE_CONFIRMED
                            || lnri.state == AwareNetworkRequestInformation.STATE_TERMINATING)) {
                return true;
            }
        }

        return false;
    }

    /**
     * Select one of the existing interfaces for the new network request. A request is canonical
     * (otherwise it wouldn't be executed).
     *
     * Construct a list of all interfaces currently used to communicate to the peer. The remaining
     * interfaces are available for use for this request - if none are left then the request should
     * fail (signaled to the caller by returning a null).
     */
    private String selectInterfaceForRequest(AwareNetworkRequestInformation req) {
        SortedSet<String> potential = new TreeSet<>(mInterfaces);
        Set<String> used = new HashSet<>();

        if (mDbg) {
            Log.v(TAG, "selectInterfaceForRequest: req=" + req + ", mNetworkRequestsCache="
                    + mNetworkRequestsCache);
        }

        for (AwareNetworkRequestInformation nnri : mNetworkRequestsCache.values()) {
            if (nnri == req) {
                continue;
            }

            if (Arrays.equals(req.peerDiscoveryMac, nnri.peerDiscoveryMac)) {
                used.add(nnri.interfaceName);
            }
        }

        if (VDBG) {
            Log.v(TAG, "selectInterfaceForRequest: potential=" + potential + ", used=" + used);
        }

        for (String ifName: potential) {
            if (!used.contains(ifName)) {
                return ifName;
            }
        }

        Log.e(TAG, "selectInterfaceForRequest: req=" + req + " - no interfaces available!");
        return null;
    }

    /**
     * Select a channel for the network request.
     *
     * TODO (b/38209409): The value from this function isn't currently used - the channel selection
     * is delegated to the HAL.
     */
    private int selectChannelForRequest(AwareNetworkRequestInformation req) {
        return 2437;
    }

    /**
     * Aware network request. State object: contains network request information/state through its
     * lifetime.
     */
    @VisibleForTesting
    public static class AwareNetworkRequestInformation {
        static final int STATE_IDLE = 100;
        static final int STATE_WAIT_FOR_CONFIRM = 101;
        static final int STATE_CONFIRMED = 102;
        static final int STATE_INITIATOR_WAIT_FOR_REQUEST_RESPONSE = 103;
        static final int STATE_RESPONDER_WAIT_FOR_REQUEST = 104;
        static final int STATE_RESPONDER_WAIT_FOR_RESPOND_RESPONSE = 105;
        static final int STATE_TERMINATING = 106;

        public int state;

        public int uid;
        public String packageName;
        public String interfaceName;
        public int pubSubId = 0;
        public int peerInstanceId = 0;
        public byte[] peerDiscoveryMac = null;
        public int ndpId = 0; // 0 is never a valid ID!
        public byte[] peerDataMac;
        public Inet6Address peerIpv6;
        public int peerPort = 0; // uninitialized (invalid) value
        public int peerTransportProtocol = -1; // uninitialized (invalid) value
        public byte[] peerIpv6Override = null;
        public WifiAwareNetworkSpecifier networkSpecifier;
        public List<NanDataPathChannelInfo> channelInfo;
        public long startTimestamp = 0; // request is made (initiator) / get request (responder)
        public long startValidationTimestamp = 0; // NDP created and starting to validate IPv6 addr

        public WifiAwareNetworkAgent networkAgent;

        /* A collection of request which are equivalent to the current request and are
         * supported by it's agent. This list DOES include the original (first) network request
         * (whose specifier is also stored separately above).
         */
        public Set<NetworkRequest> equivalentRequests = new HashSet<>();

        void updateToSupportNewRequest(NetworkRequest ns) {
            if (VDBG) Log.v(TAG, "updateToSupportNewRequest: ns=" + ns);
            if (equivalentRequests.add(ns) && state == STATE_CONFIRMED) {
                if (networkAgent == null) {
                    Log.wtf(TAG, "updateToSupportNewRequest: null agent in CONFIRMED state!?");
                    return;
                }

                networkAgent.sendNetworkCapabilities(getNetworkCapabilities());
            }
        }

        void removeSupportForRequest(NetworkRequest ns) {
            if (VDBG) Log.v(TAG, "removeSupportForRequest: ns=" + ns);
            equivalentRequests.remove(ns);

            // we will not update the agent:
            // 1. this will only get called before the agent is created
            // 2. connectivity service does not allow (WTF) updates with reduced capabilities
        }

        private NetworkCapabilities getNetworkCapabilities() {
            final NetworkCapabilities.Builder builder =
                    new NetworkCapabilities.Builder(sNetworkCapabilitiesFilter);
            builder.setNetworkSpecifier(new WifiAwareAgentNetworkSpecifier(
                    equivalentRequests.stream()
                            .map(NetworkRequest::getNetworkSpecifier)
                            .toArray(WifiAwareNetworkSpecifier[]::new)));
            if (peerIpv6 != null) {
                builder.setTransportInfo(
                        new WifiAwareNetworkInfo(peerIpv6, peerPort, peerTransportProtocol));
            }
            return builder.build();
        }

        /**
         * Returns a canonical descriptor for the network request.
         */
        CanonicalConnectionInfo getCanonicalDescriptor() {
            return new CanonicalConnectionInfo(peerDiscoveryMac, networkSpecifier.pmk,
                    networkSpecifier.sessionId, networkSpecifier.passphrase);
        }

        static AwareNetworkRequestInformation processNetworkSpecifier(NetworkRequest request,
                WifiAwareNetworkSpecifier ns, WifiAwareStateManager mgr,
                WifiPermissionsUtil wifiPermissionsUtil, WifiPermissionsWrapper permissionWrapper,
                boolean allowNdpResponderFromAnyOverride) {
            int uid, pubSubId = 0;
            int peerInstanceId = 0;
            String packageName = null;
            byte[] peerMac = ns.peerMac;

            if (VDBG) {
                Log.v(TAG, "processNetworkSpecifier: networkSpecifier=" + ns);
            }

            // type: always valid
            if (ns.type < 0
                    || ns.type > WifiAwareNetworkSpecifier.NETWORK_SPECIFIER_TYPE_MAX_VALID) {
                Log.e(TAG, "processNetworkSpecifier: networkSpecifier=" + ns
                        + ", invalid 'type' value");
                return null;
            }

            // role: always valid
            if (ns.role != WifiAwareManager.WIFI_AWARE_DATA_PATH_ROLE_INITIATOR
                    && ns.role != WifiAwareManager.WIFI_AWARE_DATA_PATH_ROLE_RESPONDER) {
                Log.e(TAG, "processNetworkSpecifier: networkSpecifier=" + ns
                        + " -- invalid 'role' value");
                return null;
            }

            if (ns.role == WifiAwareManager.WIFI_AWARE_DATA_PATH_ROLE_INITIATOR
                    && ns.type != WifiAwareNetworkSpecifier.NETWORK_SPECIFIER_TYPE_IB
                    && ns.type != WifiAwareNetworkSpecifier.NETWORK_SPECIFIER_TYPE_OOB) {
                Log.e(TAG, "processNetworkSpecifier: networkSpecifier=" + ns
                        + " -- invalid 'type' value for INITIATOR (only IB and OOB are "
                        + "permitted)");
                return null;
            }

            // look up network specifier information in Aware state manager
            WifiAwareClientState client = mgr.getClient(ns.clientId);
            if (client == null) {
                Log.e(TAG, "processNetworkSpecifier: networkSpecifier=" + ns
                        + " -- not client with this id -- clientId=" + ns.clientId);
                return null;
            }
            uid = client.getUid();
            packageName = client.getCallingPackage();

            // API change post 27: no longer allow "ANY"-style responders (initiators were never
            // permitted).
            // Note: checks are done on the manager. This is a backup for apps which bypass the
            // check.
            if (!allowNdpResponderFromAnyOverride && !wifiPermissionsUtil.isTargetSdkLessThan(
                    client.getCallingPackage(), Build.VERSION_CODES.P, uid)) {
                if (ns.type != WifiAwareNetworkSpecifier.NETWORK_SPECIFIER_TYPE_IB
                        && ns.type != WifiAwareNetworkSpecifier.NETWORK_SPECIFIER_TYPE_OOB) {
                    Log.e(TAG, "processNetworkSpecifier: networkSpecifier=" + ns
                            + " -- no ANY specifications allowed for this API level");
                    return null;
                }
            }

            // validate the port & transportProtocol
            if (ns.port < 0 || ns.transportProtocol < -1) {
                Log.e(TAG, "processNetworkSpecifier: networkSpecifier=" + ns
                        + " -- invalid port/transportProtocol");
                return null;
            }
            if (ns.port != 0 || ns.transportProtocol != -1) {
                if (ns.role != WifiAwareManager.WIFI_AWARE_DATA_PATH_ROLE_RESPONDER) {
                    Log.e(TAG, "processNetworkSpecifier: networkSpecifier=" + ns
                            + " -- port/transportProtocol can only be specified on responder");
                    return null;
                }
                if (TextUtils.isEmpty(ns.passphrase) && ns.pmk == null) {
                    Log.e(TAG, "processNetworkSpecifier: networkSpecifier=" + ns
                            + " -- port/transportProtocol can only be specified on secure ndp");
                    return null;
                }
            }

            // validate the role (if session ID provided: i.e. session 1xx)
            if (ns.type == WifiAwareNetworkSpecifier.NETWORK_SPECIFIER_TYPE_IB
                    || ns.type == WifiAwareNetworkSpecifier.NETWORK_SPECIFIER_TYPE_IB_ANY_PEER) {
                WifiAwareDiscoverySessionState session = client.getSession(ns.sessionId);
                if (session == null) {
                    Log.e(TAG,
                            "processNetworkSpecifier: networkSpecifier=" + ns
                                    + " -- no session with this id -- sessionId=" + ns.sessionId);
                    return null;
                }

                if ((session.isPublishSession()
                        && ns.role != WifiAwareManager.WIFI_AWARE_DATA_PATH_ROLE_RESPONDER) || (
                        !session.isPublishSession() && ns.role
                                != WifiAwareManager.WIFI_AWARE_DATA_PATH_ROLE_INITIATOR)) {
                    Log.e(TAG, "processNetworkSpecifier: networkSpecifier=" + ns
                            + " -- invalid role for session type");
                    return null;
                }

                if (ns.type == WifiAwareNetworkSpecifier.NETWORK_SPECIFIER_TYPE_IB) {
                    pubSubId = session.getPubSubId();
                    WifiAwareDiscoverySessionState.PeerInfo peerInfo = session.getPeerInfo(
                            ns.peerId);
                    if (peerInfo == null) {
                        Log.e(TAG, "processNetworkSpecifier: networkSpecifier=" + ns
                                + " -- no peer info associated with this peer id -- peerId="
                                + ns.peerId);
                        return null;
                    }
                    peerInstanceId = peerInfo.mInstanceId;
                    try {
                        peerMac = peerInfo.mMac;
                        if (peerMac == null || peerMac.length != 6) {
                            Log.e(TAG, "processNetworkSpecifier: networkSpecifier="
                                    + ns + " -- invalid peer MAC address");
                            return null;
                        }
                    } catch (IllegalArgumentException e) {
                        Log.e(TAG, "processNetworkSpecifier: networkSpecifier=" + ns
                                + " -- invalid peer MAC address -- e=" + e);
                        return null;
                    }
                }
            }

            // validate UID && package name
            if (request.getRequestorUid() != uid
                    || !TextUtils.equals(request.getRequestorPackageName(), packageName)) {
                Log.e(TAG, "processNetworkSpecifier: networkSpecifier=" + ns.toString()
                        + " -- UID or package name mismatch to clientId's uid=" + uid
                        + ", packageName=" + packageName);
                return null;
            }

            // validate passphrase & PMK (if provided)
            if (!TextUtils.isEmpty(ns.passphrase)) { // non-null indicates usage
                if (!WifiAwareUtils.validatePassphrase(ns.passphrase)) {
                    Log.e(TAG, "processNetworkSpecifier: networkSpecifier=" + ns.toString()
                            + " -- invalid passphrase length: " + ns.passphrase.length());
                    return null;
                }
            }
            if (ns.pmk != null && !WifiAwareUtils.validatePmk(ns.pmk)) { // non-null indicates usage
                Log.e(TAG, "processNetworkSpecifier: networkSpecifier=" + ns.toString()
                        + " -- invalid pmk length: " + ns.pmk.length);
                return null;
            }

            // create container and populate
            AwareNetworkRequestInformation nnri = new AwareNetworkRequestInformation();
            nnri.state = AwareNetworkRequestInformation.STATE_IDLE;
            nnri.uid = uid;
            nnri.packageName = packageName;
            nnri.pubSubId = pubSubId;
            nnri.peerInstanceId = peerInstanceId;
            nnri.peerDiscoveryMac = peerMac;
            nnri.networkSpecifier = ns;
            nnri.equivalentRequests.add(request);

            return nnri;
        }

        @Override
        public String toString() {
            StringBuilder sb = new StringBuilder("AwareNetworkRequestInformation: ");
            sb.append("state=").append(state).append(", ns=").append(networkSpecifier)
                    .append(", uid=").append(uid)
                    .append(", packageName=").append(packageName)
                    .append(", interfaceName=").append(interfaceName).append(
                    ", pubSubId=").append(pubSubId).append(", peerInstanceId=").append(
                    peerInstanceId).append(", peerDiscoveryMac=").append(
                    peerDiscoveryMac == null ? ""
                            : String.valueOf(HexEncoding.encode(peerDiscoveryMac))).append(
                    ", ndpId=").append(ndpId).append(", peerDataMac=").append(
                    peerDataMac == null ? ""
                            : String.valueOf(HexEncoding.encode(peerDataMac)))
                    .append(", peerIpv6=").append(peerIpv6).append(", peerPort=").append(
                    peerPort).append(", peerTransportProtocol=").append(
                    peerTransportProtocol).append(", startTimestamp=").append(
                    startTimestamp).append(", channelInfo=").append(
                    channelInfo).append(", equivalentSpecifiers=[");
            for (NetworkRequest nr : equivalentRequests) {
                sb.append(nr.toString()).append(", ");
            }
            return sb.append("]").toString();
        }
    }

    /**
     * A canonical (unique) descriptor of the peer connection.
     */
    static class CanonicalConnectionInfo {
        CanonicalConnectionInfo(byte[] peerDiscoveryMac, byte[] pmk, int sessionId,
                String passphrase) {
            this.peerDiscoveryMac = peerDiscoveryMac;
            this.pmk = pmk;
            this.sessionId = sessionId;
            this.passphrase = passphrase;
        }

        public final byte[] peerDiscoveryMac;

        /*
         * Security configuration matching:
         * - open: pmk/passphrase = null
         * - pmk: pmk != null, passphrase = null
         * - passphrase: passphrase != null, sessionId used (==0 for OOB), pmk=null
         */
        public final byte[] pmk;

        public final int sessionId;
        public final String passphrase;

        public boolean matches(CanonicalConnectionInfo other) {
            return (other.peerDiscoveryMac == null || Arrays
                    .equals(peerDiscoveryMac, other.peerDiscoveryMac))
                    && Arrays.equals(pmk, other.pmk)
                    && TextUtils.equals(passphrase, other.passphrase)
                    && (TextUtils.isEmpty(passphrase) || sessionId == other.sessionId);
        }

        @Override
        public String toString() {
            StringBuilder sb = new StringBuilder("CanonicalConnectionInfo: [");
            sb.append("peerDiscoveryMac=").append(peerDiscoveryMac == null ? ""
                    : String.valueOf(HexEncoding.encode(peerDiscoveryMac))).append(", pmk=").append(
                    pmk == null ? "" : "*").append(", sessionId=").append(sessionId).append(
                    ", passphrase=").append(passphrase == null ? "" : "*").append("]");
            return sb.toString();
        }
    }

    /**
     * Enables mocking.
     */
    @VisibleForTesting
    public class NetworkInterfaceWrapper {
        /**
         * Configures network agent properties: link-local address, connected status, interface
         * name. Delegated to enable mocking.
         */
        public boolean configureAgentProperties(AwareNetworkRequestInformation nnri,
                Set<NetworkRequest> networkRequests, int ndpId,
                NetworkCapabilities.Builder ncBuilder, LinkProperties linkProperties) {
            // find link-local address
            InetAddress linkLocal = null;
            NetworkInterface ni;
            try {
                ni = NetworkInterface.getByName(nnri.interfaceName);
            } catch (SocketException e) {
                Log.v(TAG, "onDataPathConfirm: ACCEPT nnri=" + nnri
                        + ": can't get network interface - " + e);
                return false;
            }
            if (ni == null) {
                Log.v(TAG, "onDataPathConfirm: ACCEPT nnri=" + nnri
                        + ": can't get network interface (null)");
                return false;
            }
            Enumeration<InetAddress> addresses = ni.getInetAddresses();
            while (addresses.hasMoreElements()) {
                InetAddress ip = addresses.nextElement();
                if (ip instanceof Inet6Address && ip.isLinkLocalAddress()) {
                    linkLocal = ip;
                    break;
                }
            }

            if (linkLocal == null) {
                Log.v(TAG, "onDataPathConfirm: ACCEPT nnri=" + nnri + ": no link local addresses");
                return false;
            }

            ncBuilder.setRequestorUid(nnri.uid);
            ncBuilder.setRequestorPackageName(nnri.packageName);
            ncBuilder.setNetworkSpecifier(new WifiAwareAgentNetworkSpecifier(
                    networkRequests.stream()
                            .map(NetworkRequest::getNetworkSpecifier)
                            .toArray(WifiAwareNetworkSpecifier[]::new)));

            linkProperties.setInterfaceName(nnri.interfaceName);
            linkProperties.addLinkAddress(new LinkAddress(linkLocal, 64));
            linkProperties.addRoute(
                    new RouteInfo(new IpPrefix("fe80::/64"), null, nnri.interfaceName,
                            RTN_UNICAST));

            return true;
        }

        /**
         * Tries binding to the input address to check whether it is configured (and therefore
         * usable).
         */
        public boolean isAddressUsable(LinkProperties linkProperties) {
            InetAddress address = linkProperties.getLinkAddresses().get(0).getAddress();
            DatagramSocket testDatagramSocket = null;
            try {
                testDatagramSocket = new DatagramSocket(0, address);
            } catch (SocketException e) {
                if (mDbg) {
                    Log.v(TAG, "Can't create socket on address " + address + " -- " + e);
                }
                return false;
            } finally {
                if (testDatagramSocket != null) {
                    testDatagramSocket.close();
                }
            }
            return true;
        }

        /**
         * Tell the network agent the network is now connected.
         */
        public void setConnected(WifiAwareNetworkAgent networkAgent) {
            networkAgent.markConnected();
        }
    }

    /**
     * Utility (hence static) class encapsulating the data structure used to communicate Wi-Fi Aware
     * specific network capabilities. The TLV is defined as part of the NANv3 spec:
     *
     * - Generic Service Protocol
     *   - Port
     *   - Transport protocol
     */
    @VisibleForTesting
    public static class NetworkInformationData {
        // All package visible to allow usage in unit testing
        /* package */ static final int IPV6_LL_TYPE = 0x00; // Table 82
        /* package */ static final int SERVICE_INFO_TYPE = 0x01; // Table 83
        /* package */ static final byte[] WFA_OUI = {0x50, 0x6F, (byte) 0x9A}; // Table 83
        /* package */ static final int GENERIC_SERVICE_PROTOCOL_TYPE = 0x02; // Table 50
        /* package */ static final int SUB_TYPE_PORT = 0x00; // Table 127
        /* package */ static final int SUB_TYPE_TRANSPORT_PROTOCOL = 0x01; // Table 128

        /**
         * Construct the TLV.
         */
        public static byte[] buildTlv(int port, int transportProtocol) {
            if (port == 0 && transportProtocol == -1) {
                return null;
            }

            TlvBufferUtils.TlvConstructor tlvc = new TlvBufferUtils.TlvConstructor(1, 2);
            tlvc.setByteOrder(ByteOrder.LITTLE_ENDIAN);
            tlvc.allocate(20); // safe size for now

            tlvc.putRawByteArray(WFA_OUI);
            tlvc.putRawByte((byte) GENERIC_SERVICE_PROTOCOL_TYPE);

            if (port != 0) {
                tlvc.putShort(SUB_TYPE_PORT, (short) port);
            }
            if (transportProtocol != -1) {
                tlvc.putByte(SUB_TYPE_TRANSPORT_PROTOCOL, (byte) transportProtocol);
            }

            byte[] subTypes = tlvc.getArray();

            tlvc.allocate(20);
            tlvc.putByteArray(SERVICE_INFO_TYPE, subTypes);

            return tlvc.getArray();
        }

        static class ParsedResults {
            ParsedResults(int port, int transportProtocol, byte[] ipv6Override) {
                this.port = port;
                this.transportProtocol = transportProtocol;
                this.ipv6Override = ipv6Override;
            }

            public int port = 0;
            public int transportProtocol = -1;
            public byte[] ipv6Override = null;
        }

        /**
         * Parse the TLV and returns:
         * - Null on parsing error
         * - <port | 0, transport-protocol | -1, ipv6-override | null> otherwise
         */
        public static ParsedResults parseTlv(byte[] tlvs) {
            int port = 0;
            int transportProtocol = -1;
            byte[] ipv6Override = null;

            try {
                TlvBufferUtils.TlvIterable tlvi = new TlvBufferUtils.TlvIterable(1, 2, tlvs);
                tlvi.setByteOrder(ByteOrder.LITTLE_ENDIAN);
                for (TlvBufferUtils.TlvElement tlve : tlvi) {
                    switch (tlve.type) {
                        case IPV6_LL_TYPE:
                            if (tlve.length != 8) { // 8 bytes in IPv6 address
                                Log.e(TAG, "NetworkInformationData: invalid IPv6 TLV -- length: "
                                        + tlve.length);
                                return null;
                            }
                            ipv6Override = tlve.getRawData();
                            break;
                        case SERVICE_INFO_TYPE:
                            Pair<Integer, Integer> serviceInfo = parseServiceInfoTlv(
                                    tlve.getRawData());
                            if (serviceInfo == null) {
                                return null;
                            }
                            port = serviceInfo.first;
                            transportProtocol = serviceInfo.second;
                            break;
                        default:
                            Log.w(TAG,
                                    "NetworkInformationData: ignoring unknown T -- " + tlve.type);
                            break;
                    }
                }
            } catch (Exception e) {
                Log.e(TAG, "NetworkInformationData: error parsing TLV -- " + e);
                return null;
            }
            return new ParsedResults(port, transportProtocol, ipv6Override);
        }

        /**
         * Parse the Service Info TLV:
         * - Returns null on error
         * - Returns <port | 0, transport-protocol | -1> otherwise
         */
        private static Pair<Integer, Integer> parseServiceInfoTlv(byte[] tlv) {
            int port = 0;
            int transportProtocol = -1;

            if (tlv.length < 4) {
                Log.e(TAG, "NetworkInformationData: invalid SERVICE_INFO_TYPE length");
                return null;
            }
            if (tlv[0] != WFA_OUI[0] || tlv[1] != WFA_OUI[1] || tlv[2] != WFA_OUI[2]) {
                Log.e(TAG, "NetworkInformationData: unexpected OUI");
                return null;
            }
            if (tlv[3] != GENERIC_SERVICE_PROTOCOL_TYPE) {
                Log.e(TAG, "NetworkInformationData: invalid type -- " + tlv[3]);
                return null;
            }
            TlvBufferUtils.TlvIterable subTlvi = new TlvBufferUtils.TlvIterable(1,
                    2, Arrays.copyOfRange(tlv, 4, tlv.length));
            subTlvi.setByteOrder(ByteOrder.LITTLE_ENDIAN);
            for (TlvBufferUtils.TlvElement subTlve : subTlvi) {
                switch (subTlve.type) {
                    case SUB_TYPE_PORT:
                        if (subTlve.length != 2) {
                            Log.e(TAG,
                                    "NetworkInformationData: invalid port TLV "
                                            + "length -- " + subTlve.length);
                            return null;
                        }
                        port = subTlve.getShort();
                        if (port < 0) {
                            port += -2 * (int) Short.MIN_VALUE;
                        }
                        if (port == 0) {
                            Log.e(TAG, "NetworkInformationData: invalid port "
                                    + port);
                            return null;
                        }
                        break;
                    case SUB_TYPE_TRANSPORT_PROTOCOL:
                        if (subTlve.length != 1) {
                            Log.e(TAG,  "NetworkInformationData: invalid transport "
                                    + "protocol TLV length -- " + subTlve.length);
                            return null;
                        }
                        transportProtocol = subTlve.getByte();
                        if (transportProtocol < 0) {
                            transportProtocol += -2 * (int) Byte.MIN_VALUE;
                        }
                        break;
                    default:
                        Log.w(TAG,  "NetworkInformationData: ignoring unknown "
                                + "SERVICE_INFO.T -- " + subTlve.type);
                        break;
                }
            }
            return Pair.create(port, transportProtocol);
        }
    }

    /**
     * Dump the internal state of the class.
     */
    public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
        pw.println("WifiAwareDataPathStateManager:");
        pw.println("  mInterfaces: " + mInterfaces);
        pw.println("  sNetworkCapabilitiesFilter: " + sNetworkCapabilitiesFilter);
        pw.println("  mNetworkRequestsCache: " + mNetworkRequestsCache);
        pw.println("  mNetworkFactory:");
        mNetworkFactory.dump(fd, pw, args);
    }
}
