/*
 * Copyright (C) 2017 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.googlecode.android_scripting.facade.wifi;

import android.app.Service;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.PackageManager;
import android.net.NetworkSpecifier;
import android.net.wifi.RttManager;
import android.net.wifi.RttManager.RttResult;
import android.net.wifi.WifiScanner;
import android.net.wifi.aware.AttachCallback;
import android.net.wifi.aware.ConfigRequest;
import android.net.wifi.aware.DiscoverySession;
import android.net.wifi.aware.DiscoverySessionCallback;
import android.net.wifi.aware.IdentityChangedListener;
import android.net.wifi.aware.PeerHandle;
import android.net.wifi.aware.PublishConfig;
import android.net.wifi.aware.PublishDiscoverySession;
import android.net.wifi.aware.SubscribeConfig;
import android.net.wifi.aware.SubscribeDiscoverySession;
import android.net.wifi.aware.TlvBufferUtils;
import android.net.wifi.aware.WifiAwareManager;
import android.net.wifi.aware.WifiAwareNetworkSpecifier;
import android.net.wifi.aware.WifiAwareSession;
import android.os.Bundle;
import android.os.Parcelable;
import android.os.RemoteException;
import android.text.TextUtils;
import android.util.Base64;
import android.util.SparseArray;

import com.android.internal.annotations.GuardedBy;
import com.android.modules.utils.build.SdkLevel;

import libcore.util.HexEncoding;

import com.googlecode.android_scripting.facade.EventFacade;
import com.googlecode.android_scripting.facade.FacadeManager;
import com.googlecode.android_scripting.jsonrpc.RpcReceiver;
import com.googlecode.android_scripting.rpc.Rpc;
import com.googlecode.android_scripting.rpc.RpcOptional;
import com.googlecode.android_scripting.rpc.RpcParameter;

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;

/**
 * WifiAwareManager functions.
 */
public class WifiAwareManagerFacade extends RpcReceiver {
    private final Service mService;
    private final EventFacade mEventFacade;
    private final WifiAwareStateChangedReceiver mStateChangedReceiver;

    private final Object mLock = new Object(); // lock access to the following vars

    @GuardedBy("mLock")
    private WifiAwareManager mMgr;

    @GuardedBy("mLock")
    private int mNextDiscoverySessionId = 1;
    @GuardedBy("mLock")
    private SparseArray<DiscoverySession> mDiscoverySessions = new SparseArray<>();
    private int getNextDiscoverySessionId() {
        synchronized (mLock) {
            return mNextDiscoverySessionId++;
        }
    }

    @GuardedBy("mLock")
    private int mNextSessionId = 1;
    @GuardedBy("mLock")
    private SparseArray<WifiAwareSession> mSessions = new SparseArray<>();
    private int getNextSessionId() {
        synchronized (mLock) {
            return mNextSessionId++;
        }
    }

    @GuardedBy("mLock")
    private SparseArray<Long> mMessageStartTime = new SparseArray<>();

    private static final String NS_KEY_TYPE = "type";
    private static final String NS_KEY_ROLE = "role";
    private static final String NS_KEY_CLIENT_ID = "client_id";
    private static final String NS_KEY_SESSION_ID = "session_id";
    private static final String NS_KEY_PEER_ID = "peer_id";
    private static final String NS_KEY_PEER_MAC = "peer_mac";
    private static final String NS_KEY_PMK = "pmk";
    private static final String NS_KEY_PASSPHRASE = "passphrase";
    private static final String NS_KEY_PORT = "port";
    private static final String NS_KEY_TRANSPORT_PROTOCOL = "transport_protocol";

    private static String getJsonString(WifiAwareNetworkSpecifier ns) throws JSONException {
        JSONObject j = new JSONObject();

        j.put(NS_KEY_TYPE, ns.type);
        j.put(NS_KEY_ROLE, ns.role);
        j.put(NS_KEY_CLIENT_ID, ns.clientId);
        j.put(NS_KEY_SESSION_ID, ns.sessionId);
        j.put(NS_KEY_PEER_ID, ns.peerId);
        if (ns.peerMac != null) {
            j.put(NS_KEY_PEER_MAC, Base64.encodeToString(ns.peerMac, Base64.DEFAULT));
        }
        if (ns.pmk != null) {
            j.put(NS_KEY_PMK, Base64.encodeToString(ns.pmk, Base64.DEFAULT));
        }
        if (ns.passphrase != null) {
            j.put(NS_KEY_PASSPHRASE, ns.passphrase);
        }
        if (ns.port != 0) {
            j.put(NS_KEY_PORT, ns.port);
        }
        if (ns.transportProtocol != -1) {
            j.put(NS_KEY_TRANSPORT_PROTOCOL, ns.transportProtocol);
        }

        return j.toString();
    }

    public static NetworkSpecifier getNetworkSpecifier(JSONObject j) throws JSONException {
        if (j == null) {
            return null;
        }

        int type = 0, role = 0, clientId = 0, sessionId = 0, peerId = 0;
        byte[] peerMac = null;
        byte[] pmk = null;
        String passphrase = null;
        int port = 0, transportProtocol = -1;

        if (j.has(NS_KEY_TYPE)) {
            type = j.getInt((NS_KEY_TYPE));
        }
        if (j.has(NS_KEY_ROLE)) {
            role = j.getInt((NS_KEY_ROLE));
        }
        if (j.has(NS_KEY_CLIENT_ID)) {
            clientId = j.getInt((NS_KEY_CLIENT_ID));
        }
        if (j.has(NS_KEY_SESSION_ID)) {
            sessionId = j.getInt((NS_KEY_SESSION_ID));
        }
        if (j.has(NS_KEY_PEER_ID)) {
            peerId = j.getInt((NS_KEY_PEER_ID));
        }
        if (j.has(NS_KEY_PEER_MAC)) {
            peerMac = Base64.decode(j.getString(NS_KEY_PEER_MAC), Base64.DEFAULT);
        }
        if (j.has(NS_KEY_PMK)) {
            pmk = Base64.decode(j.getString(NS_KEY_PMK), Base64.DEFAULT);
        }
        if (j.has(NS_KEY_PASSPHRASE)) {
            passphrase = j.getString(NS_KEY_PASSPHRASE);
        }
        if (j.has(NS_KEY_PORT)) {
            port = j.getInt(NS_KEY_PORT);
        }
        if (j.has(NS_KEY_TRANSPORT_PROTOCOL)) {
            transportProtocol = j.getInt(NS_KEY_TRANSPORT_PROTOCOL);
        }

        return new WifiAwareNetworkSpecifier(type, role, clientId, sessionId, peerId, peerMac, pmk,
                passphrase, port, transportProtocol);
    }

    private static String getStringOrNull(JSONObject j, String name) throws JSONException {
        if (j.isNull(name)) {
            return null;
        }
        return j.getString(name);
    }

    private static ConfigRequest getConfigRequest(JSONObject j) throws JSONException {
        if (j == null) {
            return null;
        }

        ConfigRequest.Builder builder = new ConfigRequest.Builder();

        if (j.has("Support5gBand")) {
            builder.setSupport5gBand(j.getBoolean("Support5gBand"));
        }
        if (j.has("MasterPreference")) {
            builder.setMasterPreference(j.getInt("MasterPreference"));
        }
        if (j.has("ClusterLow")) {
            builder.setClusterLow(j.getInt("ClusterLow"));
        }
        if (j.has("ClusterHigh")) {
            builder.setClusterHigh(j.getInt("ClusterHigh"));
        }
        if (j.has("DiscoveryWindowInterval")) {
            JSONArray interval = j.getJSONArray("DiscoveryWindowInterval");
            if (interval.length() != 2) {
                throw new JSONException(
                        "Expect 'DiscoveryWindowInterval' to be an array with 2 elements!");
            }
            int intervalValue = interval.getInt(ConfigRequest.NAN_BAND_24GHZ);
            if (intervalValue != ConfigRequest.DW_INTERVAL_NOT_INIT) {
                builder.setDiscoveryWindowInterval(ConfigRequest.NAN_BAND_24GHZ, intervalValue);
            }
            intervalValue = interval.getInt(ConfigRequest.NAN_BAND_5GHZ);
            if (intervalValue != ConfigRequest.DW_INTERVAL_NOT_INIT) {
                builder.setDiscoveryWindowInterval(ConfigRequest.NAN_BAND_5GHZ, intervalValue);
            }
        }

        return builder.build();
    }

    private static List<byte[]> getMatchFilter(JSONArray ja) throws JSONException {
        List<byte[]> la = new ArrayList<>();
        for (int i = 0; i < ja.length(); ++i) {
            la.add(Base64.decode(ja.getString(i).getBytes(StandardCharsets.UTF_8), Base64.DEFAULT));
        }
        return la;
    }

    private static PublishConfig getPublishConfig(JSONObject j) throws JSONException {
        if (j == null) {
            return null;
        }

        PublishConfig.Builder builder = new PublishConfig.Builder();

        if (j.has("ServiceName")) {
            builder.setServiceName(getStringOrNull(j, "ServiceName"));
        }

        if (j.has("ServiceSpecificInfo")) {
            String ssi = getStringOrNull(j, "ServiceSpecificInfo");
            if (ssi != null) {
                builder.setServiceSpecificInfo(ssi.getBytes());
            }
        }

        if (j.has("MatchFilter")) {
            byte[] bytes = Base64.decode(
                    j.getString("MatchFilter").getBytes(StandardCharsets.UTF_8), Base64.DEFAULT);
            List<byte[]> mf = new TlvBufferUtils.TlvIterable(0, 1, bytes).toList();
            builder.setMatchFilter(mf);

        }

        if (!j.isNull("MatchFilterList")) {
            builder.setMatchFilter(getMatchFilter(j.getJSONArray("MatchFilterList")));
        }

        if (j.has("DiscoveryType")) {
            builder.setPublishType(j.getInt("DiscoveryType"));
        }
        if (j.has("TtlSec")) {
            builder.setTtlSec(j.getInt("TtlSec"));
        }
        if (j.has("TerminateNotificationEnabled")) {
            builder.setTerminateNotificationEnabled(j.getBoolean("TerminateNotificationEnabled"));
        }
        if (j.has("RangingEnabled")) {
            builder.setRangingEnabled(j.getBoolean("RangingEnabled"));
        }
        if (SdkLevel.isAtLeastT() && j.has("InstantModeEnabled")) {
            builder.setInstantCommunicationModeEnabled(true,
                    Objects.equals(j.getString("InstantModeEnabled"), "5G")
                            ? WifiScanner.WIFI_BAND_5_GHZ : WifiScanner.WIFI_BAND_24_GHZ);
        }

        return builder.build();
    }

    private static SubscribeConfig getSubscribeConfig(JSONObject j) throws JSONException {
        if (j == null) {
            return null;
        }

        SubscribeConfig.Builder builder = new SubscribeConfig.Builder();

        if (j.has("ServiceName")) {
            builder.setServiceName(j.getString("ServiceName"));
        }

        if (j.has("ServiceSpecificInfo")) {
            String ssi = getStringOrNull(j, "ServiceSpecificInfo");
            if (ssi != null) {
                builder.setServiceSpecificInfo(ssi.getBytes());
            }
        }

        if (j.has("MatchFilter")) {
            byte[] bytes = Base64.decode(
                    j.getString("MatchFilter").getBytes(StandardCharsets.UTF_8), Base64.DEFAULT);
            List<byte[]> mf = new TlvBufferUtils.TlvIterable(0, 1, bytes).toList();
            builder.setMatchFilter(mf);
        }

        if (!j.isNull("MatchFilterList")) {
            builder.setMatchFilter(getMatchFilter(j.getJSONArray("MatchFilterList")));
        }

        if (j.has("DiscoveryType")) {
            builder.setSubscribeType(j.getInt("DiscoveryType"));
        }
        if (j.has("TtlSec")) {
            builder.setTtlSec(j.getInt("TtlSec"));
        }
        if (j.has("TerminateNotificationEnabled")) {
            builder.setTerminateNotificationEnabled(j.getBoolean("TerminateNotificationEnabled"));
        }
        if (j.has("MinDistanceMm")) {
            builder.setMinDistanceMm(j.getInt("MinDistanceMm"));
        }
        if (j.has("MaxDistanceMm")) {
            builder.setMaxDistanceMm(j.getInt("MaxDistanceMm"));
        }
        if (SdkLevel.isAtLeastT() && j.has("InstantModeEnabled")) {
            builder.setInstantCommunicationModeEnabled(true,
                    Objects.equals(j.getString("InstantModeEnabled"), "5G")
                            ? WifiScanner.WIFI_BAND_5_GHZ : WifiScanner.WIFI_BAND_24_GHZ);
        }

        return builder.build();
    }

    public WifiAwareManagerFacade(FacadeManager manager) {
        super(manager);
        mService = manager.getService();

        mMgr = (WifiAwareManager) mService.getSystemService(Context.WIFI_AWARE_SERVICE);

        mEventFacade = manager.getReceiver(EventFacade.class);

        mStateChangedReceiver = new WifiAwareStateChangedReceiver();
        IntentFilter filter = new IntentFilter(WifiAwareManager.ACTION_WIFI_AWARE_STATE_CHANGED);
        mService.registerReceiver(mStateChangedReceiver, filter);
    }

    @Override
    public void shutdown() {
        wifiAwareDestroyAll();
        mService.unregisterReceiver(mStateChangedReceiver);
    }

    @Rpc(description = "Does the device support the Wi-Fi Aware feature?")
    public Boolean doesDeviceSupportWifiAwareFeature() {
        return mService.getPackageManager().hasSystemFeature(PackageManager.FEATURE_WIFI_AWARE);
    }

    @Rpc(description = "Is Aware Usage Enabled?")
    public Boolean wifiIsAwareAvailable() throws RemoteException {
        synchronized (mLock) {
            return mMgr.isAvailable();
        }
    }

    @Rpc(description = "Destroy all Aware sessions and discovery sessions")
    public void wifiAwareDestroyAll() {
        synchronized (mLock) {
            for (int i = 0; i < mSessions.size(); ++i) {
                mSessions.valueAt(i).close();
            }
            mSessions.clear();

            /* discovery sessions automatically destroyed when containing Aware sessions
             * destroyed */
            mDiscoverySessions.clear();

            mMessageStartTime.clear();
        }
    }

    @Rpc(description = "Attach to Aware.")
    public Integer wifiAwareAttach(
            @RpcParameter(name = "identityCb",
                description = "Controls whether an identity callback is provided")
                @RpcOptional Boolean identityCb,
            @RpcParameter(name = "awareConfig",
                description = "The session configuration, or null for default config")
                @RpcOptional JSONObject awareConfig,
            @RpcParameter(name = "useIdInCallbackEvent",
                description =
                    "Specifies whether the callback events should be decorated with session Id")
                @RpcOptional Boolean useIdInCallbackEvent)
            throws RemoteException, JSONException {
        synchronized (mLock) {
            int sessionId = getNextSessionId();
            boolean useIdInCallbackEventName =
                (useIdInCallbackEvent != null) ? useIdInCallbackEvent : false;
            mMgr.attach(null, getConfigRequest(awareConfig),
                    new AwareAttachCallbackPostsEvents(sessionId, useIdInCallbackEventName),
                    (identityCb != null && identityCb.booleanValue())
                        ? new AwareIdentityChangeListenerPostsEvents(sessionId,
                        useIdInCallbackEventName) : null);
            return sessionId;
        }
    }

    @Rpc(description = "Destroy a Aware session.")
    public void wifiAwareDestroy(
            @RpcParameter(name = "clientId", description = "The client ID returned when a connection was created") Integer clientId)
            throws RemoteException, JSONException {
        WifiAwareSession session;
        synchronized (mLock) {
            session = mSessions.get(clientId);
        }
        if (session == null) {
            throw new IllegalStateException(
                    "Calling WifiAwareDisconnect before session (client ID " + clientId
                            + ") is ready/or already disconnected");
        }
        session.close();
    }

    @Rpc(description = "Publish.")
    public Integer wifiAwarePublish(
            @RpcParameter(name = "clientId", description = "The client ID returned when a connection was created") Integer clientId,
            @RpcParameter(name = "publishConfig") JSONObject publishConfig,
            @RpcParameter(name = "useIdInCallbackEvent",
            description =
                "Specifies whether the callback events should be decorated with session Id")
                @RpcOptional Boolean useIdInCallbackEvent)
            throws RemoteException, JSONException {
        synchronized (mLock) {
            WifiAwareSession session = mSessions.get(clientId);
            if (session == null) {
                throw new IllegalStateException(
                        "Calling WifiAwarePublish before session (client ID " + clientId
                                + ") is ready/or already disconnected");
            }
            boolean useIdInCallbackEventName =
                (useIdInCallbackEvent != null) ? useIdInCallbackEvent : false;

            int discoverySessionId = getNextDiscoverySessionId();
            session.publish(getPublishConfig(publishConfig),
                new AwareDiscoverySessionCallbackPostsEvents(discoverySessionId,
                    useIdInCallbackEventName), null);
            return discoverySessionId;
        }
    }

    @Rpc(description = "Update Publish.")
    public void wifiAwareUpdatePublish(
        @RpcParameter(name = "sessionId", description = "The discovery session ID")
            Integer sessionId,
        @RpcParameter(name = "publishConfig", description = "Publish configuration")
            JSONObject publishConfig)
        throws RemoteException, JSONException {
        synchronized (mLock) {
            DiscoverySession session = mDiscoverySessions.get(sessionId);
            if (session == null) {
                throw new IllegalStateException(
                    "Calling wifiAwareUpdatePublish before session (session ID "
                        + sessionId + ") is ready");
            }
            if (!(session instanceof PublishDiscoverySession)) {
                throw new IllegalArgumentException(
                    "Calling wifiAwareUpdatePublish with a subscribe session ID");
            }
            ((PublishDiscoverySession) session).updatePublish(getPublishConfig(publishConfig));
        }
    }

    @Rpc(description = "Subscribe.")
    public Integer wifiAwareSubscribe(
            @RpcParameter(name = "clientId", description = "The client ID returned when a connection was created") Integer clientId,
            @RpcParameter(name = "subscribeConfig") JSONObject subscribeConfig,
            @RpcParameter(name = "useIdInCallbackEvent",
                description =
                "Specifies whether the callback events should be decorated with session Id")
                @RpcOptional Boolean useIdInCallbackEvent)
            throws RemoteException, JSONException {
        synchronized (mLock) {
            WifiAwareSession session = mSessions.get(clientId);
            if (session == null) {
                throw new IllegalStateException(
                        "Calling WifiAwareSubscribe before session (client ID " + clientId
                                + ") is ready/or already disconnected");
            }
            boolean useIdInCallbackEventName =
                (useIdInCallbackEvent != null) ? useIdInCallbackEvent : false;

            int discoverySessionId = getNextDiscoverySessionId();
            session.subscribe(getSubscribeConfig(subscribeConfig),
                new AwareDiscoverySessionCallbackPostsEvents(discoverySessionId,
                    useIdInCallbackEventName), null);
            return discoverySessionId;
        }
    }

    @Rpc(description = "Update Subscribe.")
    public void wifiAwareUpdateSubscribe(
        @RpcParameter(name = "sessionId", description = "The discovery session ID")
            Integer sessionId,
        @RpcParameter(name = "subscribeConfig", description = "Subscribe configuration")
            JSONObject subscribeConfig)
        throws RemoteException, JSONException {
        synchronized (mLock) {
            DiscoverySession session = mDiscoverySessions.get(sessionId);
            if (session == null) {
                throw new IllegalStateException(
                    "Calling wifiAwareUpdateSubscribe before session (session ID "
                        + sessionId + ") is ready");
            }
            if (!(session instanceof SubscribeDiscoverySession)) {
                throw new IllegalArgumentException(
                    "Calling wifiAwareUpdateSubscribe with a publish session ID");
            }
            ((SubscribeDiscoverySession) session)
                .updateSubscribe(getSubscribeConfig(subscribeConfig));
        }
    }

    @Rpc(description = "Destroy a discovery Session.")
    public void wifiAwareDestroyDiscoverySession(
            @RpcParameter(name = "sessionId", description = "The discovery session ID returned when session was created using publish or subscribe") Integer sessionId)
            throws RemoteException {
        synchronized (mLock) {
            DiscoverySession session = mDiscoverySessions.get(sessionId);
            if (session == null) {
                throw new IllegalStateException(
                        "Calling WifiAwareTerminateSession before session (session ID "
                                + sessionId + ") is ready");
            }
            session.close();
            mDiscoverySessions.remove(sessionId);
        }
    }

    @Rpc(description = "Send peer-to-peer Aware message")
    public void wifiAwareSendMessage(
            @RpcParameter(name = "sessionId", description = "The session ID returned when session"
                    + " was created using publish or subscribe") Integer sessionId,
            @RpcParameter(name = "peerId", description = "The ID of the peer being communicated "
                    + "with. Obtained from a previous message or match session.") Integer peerId,
            @RpcParameter(name = "messageId", description = "Arbitrary handle used for "
                    + "identification of the message in the message status callbacks")
                    Integer messageId,
            @RpcParameter(name = "message") String message,
            @RpcParameter(name = "retryCount", description = "Number of retries (0 for none) if "
                    + "transmission fails due to no ACK reception") Integer retryCount)
                    throws RemoteException {
        DiscoverySession session;
        synchronized (mLock) {
            session = mDiscoverySessions.get(sessionId);
        }
        if (session == null) {
            throw new IllegalStateException(
                    "Calling WifiAwareSendMessage before session (session ID " + sessionId
                            + " is ready");
        }
        byte[] bytes = null;
        if (message != null) {
            bytes = message.getBytes();
        }

        synchronized (mLock) {
            mMessageStartTime.put(messageId, System.currentTimeMillis());
        }
        session.sendMessage(new PeerHandle(peerId), messageId, bytes, retryCount);
    }

    @Rpc(description = "Create a network specifier to be used when specifying a Aware network request")
    public String wifiAwareCreateNetworkSpecifier(
            @RpcParameter(name = "sessionId", description = "The session ID returned when session was created using publish or subscribe")
                    Integer sessionId,
            @RpcParameter(name = "peerId", description = "The ID of the peer (obtained through OnMatch or OnMessageReceived")
                    Integer peerId,
            @RpcParameter(name = "passphrase",
                description = "Passphrase of the data-path. Optional, can be empty/null.")
                @RpcOptional String passphrase,
            @RpcParameter(name = "pmk",
                description = "PMK of the data-path (base64 encoded). Optional, can be empty/null.")
                @RpcOptional String pmk,
            @RpcParameter(name = "port", description = "Port") @RpcOptional Integer port,
            @RpcParameter(name = "transportProtocol", description = "Transport protocol")
                @RpcOptional Integer transportProtocol) throws JSONException {
        DiscoverySession session;
        synchronized (mLock) {
            session = mDiscoverySessions.get(sessionId);
        }
        if (session == null) {
            throw new IllegalStateException(
                    "Calling wifiAwareCreateNetworkSpecifier before session (session ID "
                            + sessionId + " is ready");
        }
        PeerHandle peerHandle = null;
        if (peerId != null) {
            peerHandle = new PeerHandle(peerId);
        }
        byte[] pmkDecoded = null;
        if (!TextUtils.isEmpty(pmk)) {
            pmkDecoded = Base64.decode(pmk, Base64.DEFAULT);
        }

        WifiAwareNetworkSpecifier ns = new WifiAwareNetworkSpecifier(
                (peerHandle == null) ? WifiAwareNetworkSpecifier.NETWORK_SPECIFIER_TYPE_IB_ANY_PEER
                        : WifiAwareNetworkSpecifier.NETWORK_SPECIFIER_TYPE_IB,
                session instanceof SubscribeDiscoverySession
                        ? WifiAwareManager.WIFI_AWARE_DATA_PATH_ROLE_INITIATOR
                        : WifiAwareManager.WIFI_AWARE_DATA_PATH_ROLE_RESPONDER,
                session.getClientId(),
                session.getSessionId(),
                peerHandle != null ? peerHandle.peerId : 0, // 0 is an invalid peer ID
                null, // peerMac (not used in this method)
                pmkDecoded,
                passphrase,
                port == null ? 0 : port.intValue(),
                transportProtocol == null ? -1 : transportProtocol.intValue());

        return getJsonString(ns);
    }

    @Rpc(description = "Create a network specifier to be used when specifying an OOB Aware network request")
    public String wifiAwareCreateNetworkSpecifierOob(
            @RpcParameter(name = "clientId",
                    description = "The client ID")
                    Integer clientId,
            @RpcParameter(name = "role", description = "The role: INITIATOR(0), RESPONDER(1)")
                    Integer role,
            @RpcParameter(name = "peerMac",
                    description = "The MAC address of the peer")
                    String peerMac,
            @RpcParameter(name = "passphrase",
                    description = "Passphrase of the data-path. Optional, can be empty/null.")
            @RpcOptional String passphrase,
            @RpcParameter(name = "pmk",
                    description = "PMK of the data-path (base64). Optional, can be empty/null.")
            @RpcOptional String pmk) throws JSONException {
        WifiAwareSession session;
        synchronized (mLock) {
            session = mSessions.get(clientId);
        }
        if (session == null) {
            throw new IllegalStateException(
                    "Calling wifiAwareCreateNetworkSpecifierOob before session (client ID "
                            + clientId + " is ready");
        }
        byte[] peerMacBytes = null;
        if (peerMac != null) {
            peerMacBytes = HexEncoding.decode(peerMac.toCharArray(), false);
        }
        byte[] pmkDecoded = null;
        if (!TextUtils.isEmpty(pmk)) {
            pmkDecoded = Base64.decode(pmk, Base64.DEFAULT);
        }

        WifiAwareNetworkSpecifier ns = new WifiAwareNetworkSpecifier(
                (peerMacBytes == null) ?
                        WifiAwareNetworkSpecifier.NETWORK_SPECIFIER_TYPE_OOB_ANY_PEER
                        : WifiAwareNetworkSpecifier.NETWORK_SPECIFIER_TYPE_OOB,
                role,
                session.getClientId(),
                0, // 0 is an invalid session ID
                0, // 0 is an invalid peer ID
                peerMacBytes,
                pmkDecoded,
                passphrase,
                0, // no port for OOB
                -1); // no transport protocol for OOB

        return getJsonString(ns);
    }

    private class AwareAttachCallbackPostsEvents extends AttachCallback {
        private int mSessionId;
        private long mCreateTimestampMs;
        private boolean mUseIdInCallbackEventName;

        public AwareAttachCallbackPostsEvents(int sessionId, boolean useIdInCallbackEventName) {
            mSessionId = sessionId;
            mCreateTimestampMs = System.currentTimeMillis();
            mUseIdInCallbackEventName = useIdInCallbackEventName;
        }

        @Override
        public void onAttached(WifiAwareSession session) {
            synchronized (mLock) {
                mSessions.put(mSessionId, session);
            }

            Bundle mResults = new Bundle();
            mResults.putInt("sessionId", mSessionId);
            mResults.putLong("latencyMs", System.currentTimeMillis() - mCreateTimestampMs);
            mResults.putLong("timestampMs", System.currentTimeMillis());
            if (mUseIdInCallbackEventName) {
                mEventFacade.postEvent("WifiAwareOnAttached_" + mSessionId, mResults);
            } else {
                mEventFacade.postEvent("WifiAwareOnAttached", mResults);
            }
        }

        @Override
        public void onAttachFailed() {
            Bundle mResults = new Bundle();
            mResults.putInt("sessionId", mSessionId);
            mResults.putLong("latencyMs", System.currentTimeMillis() - mCreateTimestampMs);
            if (mUseIdInCallbackEventName) {
                mEventFacade.postEvent("WifiAwareOnAttachFailed_" + mSessionId, mResults);
            } else {
                mEventFacade.postEvent("WifiAwareOnAttachFailed", mResults);
            }
        }
    }

    private class AwareIdentityChangeListenerPostsEvents extends IdentityChangedListener {
        private int mSessionId;
        private boolean mUseIdInCallbackEventName;

        public AwareIdentityChangeListenerPostsEvents(int sessionId,
            boolean useIdInCallbackEventName) {
            mSessionId = sessionId;
            mUseIdInCallbackEventName = useIdInCallbackEventName;
        }

        @Override
        public void onIdentityChanged(byte[] mac) {
            Bundle mResults = new Bundle();
            mResults.putInt("sessionId", mSessionId);
            mResults.putString("mac", String.valueOf(HexEncoding.encode(mac)));
            mResults.putLong("timestampMs", System.currentTimeMillis());
            if (mUseIdInCallbackEventName) {
                mEventFacade.postEvent("WifiAwareOnIdentityChanged_" + mSessionId, mResults);
            } else {
                mEventFacade.postEvent("WifiAwareOnIdentityChanged", mResults);
            }
        }
    }

    private class AwareDiscoverySessionCallbackPostsEvents extends
            DiscoverySessionCallback {
        private int mDiscoverySessionId;
        private boolean mUseIdInCallbackEventName;
        private long mCreateTimestampMs;

        public AwareDiscoverySessionCallbackPostsEvents(int discoverySessionId,
                boolean useIdInCallbackEventName) {
            mDiscoverySessionId = discoverySessionId;
            mUseIdInCallbackEventName = useIdInCallbackEventName;
            mCreateTimestampMs = System.currentTimeMillis();
        }

        private void postEvent(String eventName, Bundle results) {
            String finalEventName = eventName;
            if (mUseIdInCallbackEventName) {
                finalEventName += "_" + mDiscoverySessionId;
            }

            mEventFacade.postEvent(finalEventName, results);
        }

        @Override
        public void onPublishStarted(PublishDiscoverySession discoverySession) {
            synchronized (mLock) {
                mDiscoverySessions.put(mDiscoverySessionId, discoverySession);
            }

            Bundle mResults = new Bundle();
            mResults.putInt("discoverySessionId", mDiscoverySessionId);
            mResults.putLong("latencyMs", System.currentTimeMillis() - mCreateTimestampMs);
            mResults.putLong("timestampMs", System.currentTimeMillis());
            postEvent("WifiAwareSessionOnPublishStarted", mResults);
        }

        @Override
        public void onSubscribeStarted(SubscribeDiscoverySession discoverySession) {
            synchronized (mLock) {
                mDiscoverySessions.put(mDiscoverySessionId, discoverySession);
            }

            Bundle mResults = new Bundle();
            mResults.putInt("discoverySessionId", mDiscoverySessionId);
            mResults.putLong("latencyMs", System.currentTimeMillis() - mCreateTimestampMs);
            mResults.putLong("timestampMs", System.currentTimeMillis());
            postEvent("WifiAwareSessionOnSubscribeStarted", mResults);
        }

        @Override
        public void onSessionConfigUpdated() {
            Bundle mResults = new Bundle();
            mResults.putInt("discoverySessionId", mDiscoverySessionId);
            postEvent("WifiAwareSessionOnSessionConfigUpdated", mResults);
        }

        @Override
        public void onSessionConfigFailed() {
            Bundle mResults = new Bundle();
            mResults.putInt("discoverySessionId", mDiscoverySessionId);
            postEvent("WifiAwareSessionOnSessionConfigFailed", mResults);
        }

        @Override
        public void onSessionTerminated() {
            Bundle mResults = new Bundle();
            mResults.putInt("discoverySessionId", mDiscoverySessionId);
            postEvent("WifiAwareSessionOnSessionTerminated", mResults);
        }

        private Bundle createServiceDiscoveredBaseBundle(PeerHandle peerHandle,
                byte[] serviceSpecificInfo, List<byte[]> matchFilter) {
            Bundle mResults = new Bundle();
            mResults.putInt("discoverySessionId", mDiscoverySessionId);
            mResults.putInt("peerId", peerHandle.peerId);
            mResults.putByteArray("serviceSpecificInfo", serviceSpecificInfo);
            mResults.putByteArray("matchFilter", new TlvBufferUtils.TlvConstructor(0,
                    1).allocateAndPut(matchFilter).getArray());
            ArrayList<String> matchFilterStrings = new ArrayList<>(matchFilter.size());
            for (byte[] be: matchFilter) {
                matchFilterStrings.add(Base64.encodeToString(be, Base64.DEFAULT));
            }
            mResults.putStringArrayList("matchFilterList", matchFilterStrings);
            mResults.putLong("timestampMs", System.currentTimeMillis());
            return mResults;
        }

        @Override
        public void onServiceDiscovered(PeerHandle peerHandle,
                byte[] serviceSpecificInfo, List<byte[]> matchFilter) {
            Bundle mResults = createServiceDiscoveredBaseBundle(peerHandle, serviceSpecificInfo,
                    matchFilter);
            postEvent("WifiAwareSessionOnServiceDiscovered", mResults);
        }

        @Override
        public void onServiceDiscoveredWithinRange(PeerHandle peerHandle,
                byte[] serviceSpecificInfo,
                List<byte[]> matchFilter, int distanceMm) {
            Bundle mResults = createServiceDiscoveredBaseBundle(peerHandle, serviceSpecificInfo,
                    matchFilter);
            mResults.putInt("distanceMm", distanceMm);
            postEvent("WifiAwareSessionOnServiceDiscovered", mResults);
        }

        @Override
        public void onMessageSendSucceeded(int messageId) {
            Bundle mResults = new Bundle();
            mResults.putInt("discoverySessionId", mDiscoverySessionId);
            mResults.putInt("messageId", messageId);
            synchronized (mLock) {
                Long startTime = mMessageStartTime.get(messageId);
                if (startTime != null) {
                    mResults.putLong("latencyMs",
                            System.currentTimeMillis() - startTime.longValue());
                    mMessageStartTime.remove(messageId);
                }
            }
            postEvent("WifiAwareSessionOnMessageSent", mResults);
        }

        @Override
        public void onMessageSendFailed(int messageId) {
            Bundle mResults = new Bundle();
            mResults.putInt("discoverySessionId", mDiscoverySessionId);
            mResults.putInt("messageId", messageId);
            synchronized (mLock) {
                Long startTime = mMessageStartTime.get(messageId);
                if (startTime != null) {
                    mResults.putLong("latencyMs",
                            System.currentTimeMillis() - startTime.longValue());
                    mMessageStartTime.remove(messageId);
                }
            }
            postEvent("WifiAwareSessionOnMessageSendFailed", mResults);
        }

        @Override
        public void onMessageReceived(PeerHandle peerHandle, byte[] message) {
            Bundle mResults = new Bundle();
            mResults.putInt("discoverySessionId", mDiscoverySessionId);
            mResults.putInt("peerId", peerHandle.peerId);
            mResults.putByteArray("message", message); // TODO: base64
            mResults.putString("messageAsString", new String(message));
            postEvent("WifiAwareSessionOnMessageReceived", mResults);
        }

        @Override
        public void onServiceLost(PeerHandle peerHandle, @WifiAwareManager.DiscoveryLostReasonCode
                int reason) {
            Bundle mResults = new Bundle();
            mResults.putInt("discoverySessionId", mDiscoverySessionId);
            mResults.putInt("peerId", peerHandle.peerId);
            mResults.putInt("lostReason", reason);
            postEvent("WifiAwareSessionOnServiceLost", mResults);
        }
    }

    class WifiAwareRangingListener implements RttManager.RttListener {
        private int mCallbackId;
        private int mSessionId;

        public WifiAwareRangingListener(int callbackId, int sessionId) {
            mCallbackId = callbackId;
            mSessionId = sessionId;
        }

        @Override
        public void onSuccess(RttResult[] results) {
            Bundle bundle = new Bundle();
            bundle.putInt("callbackId", mCallbackId);
            bundle.putInt("sessionId", mSessionId);

            Parcelable[] resultBundles = new Parcelable[results.length];
            for (int i = 0; i < results.length; i++) {
                resultBundles[i] = WifiRttManagerFacade.RangingListener.packRttResult(results[i]);
            }
            bundle.putParcelableArray("Results", resultBundles);

            mEventFacade.postEvent("WifiAwareRangingListenerOnSuccess", bundle);
        }

        @Override
        public void onFailure(int reason, String description) {
            Bundle bundle = new Bundle();
            bundle.putInt("callbackId", mCallbackId);
            bundle.putInt("sessionId", mSessionId);
            bundle.putInt("reason", reason);
            bundle.putString("description", description);
            mEventFacade.postEvent("WifiAwareRangingListenerOnFailure", bundle);
        }

        @Override
        public void onAborted() {
            Bundle bundle = new Bundle();
            bundle.putInt("callbackId", mCallbackId);
            bundle.putInt("sessionId", mSessionId);
            mEventFacade.postEvent("WifiAwareRangingListenerOnAborted", bundle);
        }

    }

    class WifiAwareStateChangedReceiver extends BroadcastReceiver {
        @Override
        public void onReceive(Context c, Intent intent) {
            boolean isAvailable = mMgr.isAvailable();
            if (!isAvailable) {
                wifiAwareDestroyAll();
            }
            mEventFacade.postEvent(isAvailable ? "WifiAwareAvailable" : "WifiAwareNotAvailable",
                    new Bundle());
        }
    }
}
