wpa_supplicant: Add P2P |Iface| & |Network| classes

Add the new P2P iface/network HIDL interface implementations. This CL
only implements methods from the base class
|ISupplicantIface|/|ISupplicantNetwork| to the p2p classes.

Bug: 31497295
Test: Compiles
Change-Id: Ie0876f16ef58fe73f0eabd302c964523de5d5041
diff --git a/wpa_supplicant/Android.mk b/wpa_supplicant/Android.mk
index 019bf9f..1a25d08 100644
--- a/wpa_supplicant/Android.mk
+++ b/wpa_supplicant/Android.mk
@@ -1669,6 +1669,8 @@
 LOCAL_SRC_FILES := \
     hidl/hidl.cpp \
     hidl/hidl_manager.cpp \
+    hidl/p2p_iface.cpp \
+    hidl/p2p_network.cpp \
     hidl/sta_iface.cpp \
     hidl/sta_network.cpp \
     hidl/supplicant.cpp
diff --git a/wpa_supplicant/hidl/p2p_iface.cpp b/wpa_supplicant/hidl/p2p_iface.cpp
new file mode 100644
index 0000000..e9ee986
--- /dev/null
+++ b/wpa_supplicant/hidl/p2p_iface.cpp
@@ -0,0 +1,170 @@
+/*
+ * hidl interface for wpa_supplicant daemon
+ * Copyright (c) 2004-2016, Jouni Malinen <j@w1.fi>
+ * Copyright (c) 2004-2016, Roshan Pius <rpius@google.com>
+ *
+ * This software may be distributed under the terms of the BSD license.
+ * See README for more details.
+ */
+
+#include "hidl_manager.h"
+#include "hidl_return_macros.h"
+#include "p2p_iface.h"
+
+namespace android {
+namespace hardware {
+namespace wifi {
+namespace supplicant {
+namespace V1_0 {
+namespace implementation {
+
+P2pIface::P2pIface(struct wpa_global *wpa_global, const char ifname[])
+    : wpa_global_(wpa_global), ifname_(ifname)
+{
+}
+
+Return<void> P2pIface::getName(getName_cb _hidl_cb)
+{
+	struct wpa_supplicant *wpa_s = retrieveP2pIfacePtr();
+	if (!wpa_s) {
+		HIDL_RETURN(
+		    SupplicantStatusCode::FAILURE_IFACE_INVALID, ifname_);
+	}
+
+	HIDL_RETURN(SupplicantStatusCode::SUCCESS, ifname_);
+}
+
+Return<void> P2pIface::getType(getType_cb _hidl_cb)
+{
+	struct wpa_supplicant *wpa_s = retrieveP2pIfacePtr();
+	if (!wpa_s) {
+		HIDL_RETURN(
+		    SupplicantStatusCode::FAILURE_IFACE_INVALID,
+		    IfaceType::STA);
+	}
+
+	HIDL_RETURN(SupplicantStatusCode::SUCCESS, IfaceType::STA);
+}
+
+Return<void> P2pIface::addNetwork(addNetwork_cb _hidl_cb)
+{
+	android::sp<ISupplicantP2pNetwork> network;
+	struct wpa_supplicant *wpa_s = retrieveP2pIfacePtr();
+	if (!wpa_s) {
+		HIDL_RETURN(
+		    SupplicantStatusCode::FAILURE_IFACE_INVALID, network);
+	}
+
+	struct wpa_ssid *ssid = wpa_supplicant_add_network(wpa_s);
+	if (!ssid) {
+		HIDL_RETURN(SupplicantStatusCode::FAILURE_UNKNOWN, network);
+	}
+
+	HidlManager *hidl_manager = HidlManager::getInstance();
+	if (!hidl_manager ||
+	    hidl_manager->getP2pNetworkHidlObjectByIfnameAndNetworkId(
+		wpa_s->ifname, ssid->id, &network)) {
+		HIDL_RETURN(SupplicantStatusCode::FAILURE_UNKNOWN, network);
+	}
+
+	HIDL_RETURN(SupplicantStatusCode::SUCCESS, network);
+}
+
+Return<void> P2pIface::removeNetwork(uint32_t id, removeNetwork_cb _hidl_cb)
+{
+	struct wpa_supplicant *wpa_s = retrieveP2pIfacePtr();
+	if (!wpa_s) {
+		HIDL_RETURN(SupplicantStatusCode::FAILURE_IFACE_INVALID);
+	}
+
+	int result = wpa_supplicant_remove_network(wpa_s, id);
+	if (result == -1) {
+		HIDL_RETURN(SupplicantStatusCode::FAILURE_NETWORK_UNKNOWN);
+	}
+
+	if (result != 0) {
+		HIDL_RETURN(SupplicantStatusCode::FAILURE_UNKNOWN);
+	}
+
+	HIDL_RETURN(SupplicantStatusCode::SUCCESS);
+}
+
+Return<void> P2pIface::getNetwork(uint32_t id, getNetwork_cb _hidl_cb)
+{
+	android::sp<ISupplicantP2pNetwork> network;
+	struct wpa_supplicant *wpa_s = retrieveP2pIfacePtr();
+	if (!wpa_s) {
+		HIDL_RETURN(
+		    SupplicantStatusCode::FAILURE_IFACE_INVALID, network);
+	}
+
+	struct wpa_ssid *ssid = wpa_config_get_network(wpa_s->conf, id);
+	if (!ssid) {
+		HIDL_RETURN(
+		    SupplicantStatusCode::FAILURE_NETWORK_UNKNOWN, network);
+	}
+
+	HidlManager *hidl_manager = HidlManager::getInstance();
+	if (!hidl_manager ||
+	    hidl_manager->getP2pNetworkHidlObjectByIfnameAndNetworkId(
+		wpa_s->ifname, ssid->id, &network)) {
+		HIDL_RETURN(SupplicantStatusCode::FAILURE_UNKNOWN, network);
+	}
+
+	HIDL_RETURN(SupplicantStatusCode::SUCCESS, network);
+}
+
+Return<void> P2pIface::listNetworks(listNetworks_cb _hidl_cb)
+{
+	std::vector<uint32_t> network_ids;
+
+	struct wpa_supplicant *wpa_s = retrieveP2pIfacePtr();
+	if (!wpa_s) {
+		HIDL_RETURN(
+		    SupplicantStatusCode::FAILURE_IFACE_INVALID, network_ids);
+	}
+
+	for (struct wpa_ssid *wpa_ssid = wpa_s->conf->ssid; wpa_ssid;
+	     wpa_ssid = wpa_ssid->next) {
+		network_ids.emplace_back(wpa_ssid->id);
+	}
+
+	HIDL_RETURN(SupplicantStatusCode::SUCCESS, network_ids);
+}
+
+Return<void> P2pIface::registerCallback(
+    const sp<ISupplicantP2pIfaceCallback> &callback,
+    registerCallback_cb _hidl_cb)
+{
+	struct wpa_supplicant *wpa_s = retrieveP2pIfacePtr();
+	if (!wpa_s) {
+		HIDL_RETURN(SupplicantStatusCode::FAILURE_IFACE_INVALID);
+	}
+
+	HidlManager *hidl_manager = HidlManager::getInstance();
+	if (!hidl_manager ||
+	    hidl_manager->addP2pIfaceCallbackHidlObject(ifname_, callback)) {
+		HIDL_RETURN(SupplicantStatusCode::FAILURE_UNKNOWN);
+	}
+
+	HIDL_RETURN(SupplicantStatusCode::SUCCESS);
+}
+
+/**
+ * Retrieve the underlying |wpa_supplicant| struct
+ * pointer for this iface.
+ * If the underlying iface is removed, then all RPC method calls on this object
+ * will return failure.
+ */
+wpa_supplicant *P2pIface::retrieveP2pIfacePtr()
+{
+	return wpa_supplicant_get_iface(
+	    (struct wpa_global *)wpa_global_, ifname_.c_str());
+}
+
+}  // namespace implementation
+}  // namespace V1_0
+}  // namespace wifi
+}  // namespace supplicant
+}  // namespace hardware
+}  // namespace android
diff --git a/wpa_supplicant/hidl/p2p_iface.h b/wpa_supplicant/hidl/p2p_iface.h
new file mode 100644
index 0000000..a003cf5
--- /dev/null
+++ b/wpa_supplicant/hidl/p2p_iface.h
@@ -0,0 +1,77 @@
+/*
+ * hidl interface for wpa_supplicant daemon
+ * Copyright (c) 2004-2016, Jouni Malinen <j@w1.fi>
+ * Copyright (c) 2004-2016, Roshan Pius <rpius@google.com>
+ *
+ * This software may be distributed under the terms of the BSD license.
+ * See README for more details.
+ */
+
+#ifndef WPA_SUPPLICANT_HIDL_P2P_IFACE_H
+#define WPA_SUPPLICANT_HIDL_P2P_IFACE_H
+
+#include <android-base/macros.h>
+
+#include <android/hardware/wifi/supplicant/1.0/ISupplicantP2pIface.h>
+#include <android/hardware/wifi/supplicant/1.0/ISupplicantP2pIfaceCallback.h>
+#include <android/hardware/wifi/supplicant/1.0/ISupplicantP2pNetwork.h>
+
+extern "C" {
+#include "utils/common.h"
+#include "utils/includes.h"
+#include "wpa_supplicant_i.h"
+#include "config.h"
+#include "driver_i.h"
+}
+
+namespace android {
+namespace hardware {
+namespace wifi {
+namespace supplicant {
+namespace V1_0 {
+namespace implementation {
+
+/**
+ * Implementation of P2pIface hidl object. Each unique hidl
+ * object is used for control operations on a specific interface
+ * controlled by wpa_supplicant.
+ */
+class P2pIface
+    : public android::hardware::wifi::supplicant::V1_0::ISupplicantP2pIface
+{
+public:
+	P2pIface(struct wpa_global* wpa_global, const char ifname[]);
+	~P2pIface() override = default;
+
+	// Hidl methods exposed.
+	Return<void> getName(getName_cb _hidl_cb) override;
+	Return<void> getType(getType_cb _hidl_cb) override;
+	Return<void> addNetwork(addNetwork_cb _hidl_cb) override;
+	Return<void> removeNetwork(
+	    uint32_t id, removeNetwork_cb _hidl_cb) override;
+	Return<void> getNetwork(uint32_t id, getNetwork_cb _hidl_cb) override;
+	Return<void> listNetworks(listNetworks_cb _hidl_cb) override;
+	Return<void> registerCallback(
+	    const sp<ISupplicantP2pIfaceCallback>& callback,
+	    registerCallback_cb _hidl_cb) override;
+
+private:
+	struct wpa_supplicant* retrieveP2pIfacePtr();
+
+	// Reference to the global wpa_struct. This is assumed to be valid for
+	// the lifetime of the process.
+	const struct wpa_global* wpa_global_;
+	// Name of the iface this hidl object controls
+	const std::string ifname_;
+
+	DISALLOW_COPY_AND_ASSIGN(P2pIface);
+};
+
+}  // namespace implementation
+}  // namespace V1_0
+}  // namespace wifi
+}  // namespace supplicant
+}  // namespace hardware
+}  // namespace android
+
+#endif  // WPA_SUPPLICANT_HIDL_P2P_IFACE_H
diff --git a/wpa_supplicant/hidl/p2p_network.cpp b/wpa_supplicant/hidl/p2p_network.cpp
new file mode 100644
index 0000000..7de950e
--- /dev/null
+++ b/wpa_supplicant/hidl/p2p_network.cpp
@@ -0,0 +1,110 @@
+/*
+ * hidl interface for wpa_supplicant daemon
+ * Copyright (c) 2004-2016, Jouni Malinen <j@w1.fi>
+ * Copyright (c) 2004-2016, Roshan Pius <rpius@google.com>
+ *
+ * This software may be distributed under the terms of the BSD license.
+ * See README for more details.
+ */
+
+#include "hidl_manager.h"
+#include "hidl_return_macros.h"
+#include "p2p_network.h"
+
+namespace android {
+namespace hardware {
+namespace wifi {
+namespace supplicant {
+namespace V1_0 {
+namespace implementation {
+
+P2pNetwork::P2pNetwork(
+    struct wpa_global *wpa_global, const char ifname[], int network_id)
+    : wpa_global_(wpa_global), ifname_(ifname), network_id_(network_id)
+{
+}
+
+Return<void> P2pNetwork::getId(getId_cb _hidl_cb)
+{
+	uint32_t id = UINT32_MAX;
+	struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
+	if (!wpa_ssid) {
+		HIDL_RETURN(SupplicantStatusCode::FAILURE_NETWORK_INVALID, id);
+	}
+
+	id = network_id_;
+	HIDL_RETURN(SupplicantStatusCode::SUCCESS, id);
+}
+
+Return<void> P2pNetwork::getInterfaceName(getInterfaceName_cb _hidl_cb)
+{
+	struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
+	if (!wpa_ssid) {
+		HIDL_RETURN(
+		    SupplicantStatusCode::FAILURE_NETWORK_INVALID, ifname_);
+	}
+
+	HIDL_RETURN(SupplicantStatusCode::SUCCESS, ifname_);
+}
+
+Return<void> P2pNetwork::getType(getType_cb _hidl_cb)
+{
+	struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
+	if (!wpa_ssid) {
+		HIDL_RETURN(
+		    SupplicantStatusCode::FAILURE_IFACE_INVALID,
+		    IfaceType::P2P);
+	}
+
+	HIDL_RETURN(SupplicantStatusCode::SUCCESS, IfaceType::P2P);
+}
+
+Return<void> P2pNetwork::registerCallback(
+    const sp<ISupplicantP2pNetworkCallback> &callback,
+    registerCallback_cb _hidl_cb)
+{
+	struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
+	if (!wpa_ssid) {
+		HIDL_RETURN(SupplicantStatusCode::FAILURE_NETWORK_INVALID);
+	}
+
+	HidlManager *hidl_manager = HidlManager::getInstance();
+	if (!hidl_manager ||
+	    hidl_manager->addP2pNetworkCallbackHidlObject(
+		ifname_, network_id_, callback)) {
+		HIDL_RETURN(SupplicantStatusCode::FAILURE_UNKNOWN);
+	}
+
+	HIDL_RETURN(SupplicantStatusCode::SUCCESS);
+}
+
+/**
+ * Retrieve the underlying |wpa_ssid| struct pointer for
+ * this network.
+ * If the underlying network is removed or the interface
+ * this network belong to is removed, all RPC method calls
+ * on this object will return failure.
+ */
+struct wpa_ssid *P2pNetwork::retrieveNetworkPtr()
+{
+	wpa_supplicant *wpa_s = retrieveIfacePtr();
+	if (!wpa_s)
+		return nullptr;
+	return wpa_config_get_network(wpa_s->conf, network_id_);
+}
+
+/**
+ * Retrieve the underlying |wpa_supplicant| struct
+ * pointer for this network.
+ */
+struct wpa_supplicant *P2pNetwork::retrieveIfacePtr()
+{
+	return wpa_supplicant_get_iface(
+	    (struct wpa_global *)wpa_global_, ifname_.c_str());
+}
+}  // namespace implementation
+}  // namespace V1_0
+}  // namespace wifi
+}  // namespace supplicant
+}  // namespace hardware
+}  // namespace android
diff --git a/wpa_supplicant/hidl/p2p_network.h b/wpa_supplicant/hidl/p2p_network.h
new file mode 100644
index 0000000..92eddd2
--- /dev/null
+++ b/wpa_supplicant/hidl/p2p_network.h
@@ -0,0 +1,78 @@
+/*
+ * hidl interface for wpa_supplicant daemon
+ * Copyright (c) 2004-2016, Jouni Malinen <j@w1.fi>
+ * Copyright (c) 2004-2016, Roshan Pius <rpius@google.com>
+ *
+ * This software may be distributed under the terms of the BSD license.
+ * See README for more details.
+ */
+
+#ifndef WPA_SUPPLICANT_HIDL_P2P_NETWORK_H
+#define WPA_SUPPLICANT_HIDL_P2P_NETWORK_H
+
+#include <android-base/macros.h>
+
+#include <android/hardware/wifi/supplicant/1.0/ISupplicantP2pNetwork.h>
+#include <android/hardware/wifi/supplicant/1.0/ISupplicantP2pNetworkCallback.h>
+
+extern "C" {
+#include "utils/common.h"
+#include "utils/includes.h"
+#include "config.h"
+#include "wpa_supplicant_i.h"
+#include "notify.h"
+#include "eapol_supp/eapol_supp_sm.h"
+#include "eap_peer/eap.h"
+#include "rsn_supp/wpa.h"
+}
+
+namespace android {
+namespace hardware {
+namespace wifi {
+namespace supplicant {
+namespace V1_0 {
+namespace implementation {
+
+/**
+ * Implementation of P2pNetwork hidl object. Each unique hidl
+ * object is used for control operations on a specific network
+ * controlled by wpa_supplicant.
+ */
+class P2pNetwork : public ISupplicantP2pNetwork
+{
+public:
+	P2pNetwork(
+	    struct wpa_global* wpa_global, const char ifname[], int network_id);
+	~P2pNetwork() override = default;
+
+	// Hidl methods exposed.
+	Return<void> getId(getId_cb _hidl_cb) override;
+	Return<void> getInterfaceName(getInterfaceName_cb _hidl_cb) override;
+	Return<void> getType(getType_cb _hidl_cb) override;
+	Return<void> registerCallback(
+	    const sp<ISupplicantP2pNetworkCallback>& callback,
+	    registerCallback_cb _hidl_cb) override;
+
+private:
+	struct wpa_ssid* retrieveNetworkPtr();
+	struct wpa_supplicant* retrieveIfacePtr();
+
+	// Reference to the global wpa_struct. This is assumed to be valid
+	// for the lifetime of the process.
+	const struct wpa_global* wpa_global_;
+	// Name of the iface this network belongs to.
+	const std::string ifname_;
+	// Id of the network this hidl object controls.
+	const int network_id_;
+
+	DISALLOW_COPY_AND_ASSIGN(P2pNetwork);
+};
+
+}  // namespace implementation
+}  // namespace V1_0
+}  // namespace wifi
+}  // namespace supplicant
+}  // namespace hardware
+}  // namespace android
+
+#endif  // WPA_SUPPLICANT_HIDL_P2P_NETWORK_H