wpa_supplicant: HIDL implementation (1/2)

Renamed all file and variable names to "HIDL" from "Binder"/"AIDL".

Commands run:
rename 's/binder/hidl/' *
find . -type f -exec sed -i "s/binder/hidl/g" {} \;
find . -type f -exec sed -i "s/Binder/Hidl/g" {} \;
find . -type f -exec sed -i "s/BINDER/HIDL/g" {} \;

Bug: 31365276
Test: None
Change-Id: I435f91540027d55143eebc03afdbf463b5b092f7
diff --git a/wpa_supplicant/hidl/.clang-format b/wpa_supplicant/hidl/.clang-format
new file mode 100644
index 0000000..42fadb5
--- /dev/null
+++ b/wpa_supplicant/hidl/.clang-format
@@ -0,0 +1,9 @@
+BasedOnStyle: Google
+IndentWidth: 8
+UseTab: Always
+BreakBeforeBraces: Mozilla
+AllowShortIfStatementsOnASingleLine: false
+IndentCaseLabels: false
+AccessModifierOffset: -8
+AlignAfterOpenBracket: AlwaysBreak
+SortIncludes: false
diff --git a/wpa_supplicant/hidl/hidl.cpp b/wpa_supplicant/hidl/hidl.cpp
new file mode 100644
index 0000000..258fa2b
--- /dev/null
+++ b/wpa_supplicant/hidl/hidl.cpp
@@ -0,0 +1,189 @@
+/*
+ * 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/IPCThreadState.h>
+#include <hidl/IServiceManager.h>
+#include <hidl/ProcessState.h>
+
+#include "hidl_manager.h"
+
+extern "C" {
+#include "hidl.h"
+#include "hidl_i.h"
+#include "utils/common.h"
+#include "utils/eloop.h"
+#include "utils/includes.h"
+}
+
+void wpas_hidl_sock_handler(
+    int /* sock */, void * /* eloop_ctx */, void *sock_ctx)
+{
+	struct wpas_hidl_priv *priv = (wpas_hidl_priv *)sock_ctx;
+	wpa_printf(
+	    MSG_DEBUG, "Processing hidl events on FD %d", priv->hidl_fd);
+	android::IPCThreadState::self()->handlePolledCommands();
+}
+
+struct wpas_hidl_priv *wpas_hidl_init(struct wpa_global *global)
+{
+	struct wpas_hidl_priv *priv;
+	wpa_supplicant_hidl::HidlManager *hidl_manager;
+
+	priv = (wpas_hidl_priv *)os_zalloc(sizeof(*priv));
+	if (!priv)
+		return NULL;
+	priv->global = global;
+
+	wpa_printf(MSG_DEBUG, "Initing hidl control");
+
+	android::ProcessState::self()->setThreadPoolMaxThreadCount(0);
+	android::IPCThreadState::self()->disableBackgroundScheduling(true);
+	android::IPCThreadState::self()->setupPolling(&priv->hidl_fd);
+	if (priv->hidl_fd < 0)
+		goto err;
+
+	wpa_printf(
+	    MSG_INFO, "Processing hidl events on FD %d", priv->hidl_fd);
+	/* Look for read events from the hidl socket in the eloop. */
+	if (eloop_register_read_sock(
+		priv->hidl_fd, wpas_hidl_sock_handler, global, priv) < 0)
+		goto err;
+
+	hidl_manager = wpa_supplicant_hidl::HidlManager::getInstance();
+	if (!hidl_manager)
+		goto err;
+	hidl_manager->registerHidlService(global);
+	/* We may not need to store this hidl manager reference in the
+	 * global data strucure because we've made it a singleton class. */
+	priv->hidl_manager = (void *)hidl_manager;
+
+	return priv;
+err:
+	wpas_hidl_deinit(priv);
+	return NULL;
+}
+
+void wpas_hidl_deinit(struct wpas_hidl_priv *priv)
+{
+	if (!priv)
+		return;
+
+	wpa_printf(MSG_DEBUG, "Deiniting hidl control");
+
+	wpa_supplicant_hidl::HidlManager::destroyInstance();
+	eloop_unregister_read_sock(priv->hidl_fd);
+	android::IPCThreadState::shutdown();
+	os_free(priv);
+}
+
+int wpas_hidl_register_interface(struct wpa_supplicant *wpa_s)
+{
+	if (!wpa_s || !wpa_s->global->hidl)
+		return 1;
+
+	wpa_printf(
+	    MSG_DEBUG, "Registering interface to hidl control: %s",
+	    wpa_s->ifname);
+
+	wpa_supplicant_hidl::HidlManager *hidl_manager =
+	    wpa_supplicant_hidl::HidlManager::getInstance();
+	if (!hidl_manager)
+		return 1;
+
+	return hidl_manager->registerInterface(wpa_s);
+}
+
+int wpas_hidl_unregister_interface(struct wpa_supplicant *wpa_s)
+{
+	if (!wpa_s || !wpa_s->global->hidl)
+		return 1;
+
+	wpa_printf(
+	    MSG_DEBUG, "Deregistering interface from hidl control: %s",
+	    wpa_s->ifname);
+
+	wpa_supplicant_hidl::HidlManager *hidl_manager =
+	    wpa_supplicant_hidl::HidlManager::getInstance();
+	if (!hidl_manager)
+		return 1;
+
+	return hidl_manager->unregisterInterface(wpa_s);
+}
+
+int wpas_hidl_register_network(
+    struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid)
+{
+	if (!wpa_s || !wpa_s->global->hidl || !ssid)
+		return 1;
+
+	wpa_printf(
+	    MSG_DEBUG, "Registering network to hidl control: %d", ssid->id);
+
+	wpa_supplicant_hidl::HidlManager *hidl_manager =
+	    wpa_supplicant_hidl::HidlManager::getInstance();
+	if (!hidl_manager)
+		return 1;
+
+	return hidl_manager->registerNetwork(wpa_s, ssid);
+}
+
+int wpas_hidl_unregister_network(
+    struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid)
+{
+	if (!wpa_s || !wpa_s->global->hidl || !ssid)
+		return 1;
+
+	wpa_printf(
+	    MSG_DEBUG, "Deregistering network from hidl control: %d",
+	    ssid->id);
+
+	wpa_supplicant_hidl::HidlManager *hidl_manager =
+	    wpa_supplicant_hidl::HidlManager::getInstance();
+	if (!hidl_manager)
+		return 1;
+
+	return hidl_manager->unregisterNetwork(wpa_s, ssid);
+}
+
+int wpas_hidl_notify_state_changed(struct wpa_supplicant *wpa_s)
+{
+	if (!wpa_s || !wpa_s->global->hidl)
+		return 1;
+
+	wpa_printf(
+	    MSG_DEBUG, "Notifying state change event to hidl control: %d",
+	    wpa_s->wpa_state);
+
+	wpa_supplicant_hidl::HidlManager *hidl_manager =
+	    wpa_supplicant_hidl::HidlManager::getInstance();
+	if (!hidl_manager)
+		return 1;
+
+	return hidl_manager->notifyStateChange(wpa_s);
+}
+
+int wpas_hidl_notify_network_request(
+    struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid,
+    enum wpa_ctrl_req_type rtype, const char *default_txt)
+{
+	if (!wpa_s || !wpa_s->global->hidl || !ssid)
+		return 1;
+
+	wpa_printf(
+	    MSG_DEBUG, "Notifying network request to hidl control: %d",
+	    ssid->id);
+
+	wpa_supplicant_hidl::HidlManager *hidl_manager =
+	    wpa_supplicant_hidl::HidlManager::getInstance();
+	if (!hidl_manager)
+		return 1;
+
+	return hidl_manager->notifyNetworkRequest(
+	    wpa_s, ssid, rtype, default_txt);
+}
diff --git a/wpa_supplicant/hidl/hidl.h b/wpa_supplicant/hidl/hidl.h
new file mode 100644
index 0000000..594098d
--- /dev/null
+++ b/wpa_supplicant/hidl/hidl.h
@@ -0,0 +1,74 @@
+/*
+ * 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_HIDL_H
+#define WPA_SUPPLICANT_HIDL_HIDL_H
+
+#ifdef _cplusplus
+extern "C" {
+#endif /* _cplusplus */
+
+/**
+ * This is the hidl RPC interface entry point to the wpa_supplicant core.
+ * This initializes the hidl driver & HidlManager instance and then forwards
+ * all the notifcations from the supplicant core to the HidlManager.
+ */
+struct wpas_hidl_priv;
+struct wpa_global;
+
+struct wpas_hidl_priv *wpas_hidl_init(struct wpa_global *global);
+void wpas_hidl_deinit(struct wpas_hidl_priv *priv);
+
+#ifdef CONFIG_CTRL_IFACE_HIDL
+int wpas_hidl_register_interface(struct wpa_supplicant *wpa_s);
+int wpas_hidl_unregister_interface(struct wpa_supplicant *wpa_s);
+int wpas_hidl_register_network(
+    struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid);
+int wpas_hidl_unregister_network(
+    struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid);
+int wpas_hidl_notify_state_changed(struct wpa_supplicant *wpa_s);
+int wpas_hidl_notify_network_request(
+    struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid,
+    enum wpa_ctrl_req_type rtype, const char *default_txt);
+#else  /* CONFIG_CTRL_IFACE_HIDL */
+static inline int wpas_hidl_register_interface(struct wpa_supplicant *wpa_s)
+{
+	return 0;
+}
+static inline int wpas_hidl_unregister_interface(struct wpa_supplicant *wpa_s)
+{
+	return 0;
+}
+static inline int wpas_hidl_register_network(
+    struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid)
+{
+	return 0;
+}
+static inline int wpas_hidl_unregister_network(
+    struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid)
+{
+	return 0;
+}
+static inline int wpas_hidl_notify_state_changed(struct wpa_supplicant *wpa_s)
+{
+	return 0;
+}
+static inline int wpas_hidl_notify_network_request(
+    struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid,
+    enum wpa_ctrl_req_type rtype, const char *default_txt)
+{
+	return 0;
+}
+#endif /* CONFIG_CTRL_IFACE_HIDL */
+
+#ifdef _cplusplus
+}
+#endif /* _cplusplus */
+
+#endif /* WPA_SUPPLICANT_HIDL_HIDL_H */
diff --git a/wpa_supplicant/hidl/hidl_constants.h b/wpa_supplicant/hidl/hidl_constants.h
new file mode 100644
index 0000000..988a590
--- /dev/null
+++ b/wpa_supplicant/hidl/hidl_constants.h
@@ -0,0 +1,21 @@
+/*
+ * 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_HIDL_CONSTANTS_H
+#define WPA_SUPPLICANT_HIDL_HIDL_CONSTANTS_H
+
+namespace wpa_supplicant_hidl {
+namespace hidl_constants {
+
+extern const char kServiceName[];
+
+} /* namespace hidl_constants */
+} /* namespace wpa_supplicant_hidl */
+
+#endif /* WPA_SUPPLICANT_HIDL_HIDL_CONSTANTS_H */
diff --git a/wpa_supplicant/hidl/hidl_i.h b/wpa_supplicant/hidl/hidl_i.h
new file mode 100644
index 0000000..8c0df2e
--- /dev/null
+++ b/wpa_supplicant/hidl/hidl_i.h
@@ -0,0 +1,28 @@
+/*
+ * 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 HIDL_I_H
+#define HIDL_I_H
+
+#ifdef _cplusplus
+extern "C" {
+#endif  // _cplusplus
+
+struct wpas_hidl_priv
+{
+	int hidl_fd;
+	struct wpa_global *global;
+	void *hidl_manager;
+};
+
+#ifdef _cplusplus
+}
+#endif /* _cplusplus */
+
+#endif /* HIDL_I_H */
diff --git a/wpa_supplicant/hidl/hidl_manager.cpp b/wpa_supplicant/hidl/hidl_manager.cpp
new file mode 100644
index 0000000..89339c5
--- /dev/null
+++ b/wpa_supplicant/hidl/hidl_manager.cpp
@@ -0,0 +1,620 @@
+/*
+ * 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 <algorithm>
+
+#include <hidl/IServiceManager.h>
+
+#include "hidl_constants.h"
+#include "hidl_manager.h"
+#include "wpa_supplicant_hidl/hidl_constants.h"
+
+extern "C" {
+#include "utils/common.h"
+#include "utils/includes.h"
+}
+
+namespace wpa_supplicant_hidl {
+
+HidlManager *HidlManager::instance_ = NULL;
+
+HidlManager *HidlManager::getInstance()
+{
+	if (!instance_)
+		instance_ = new HidlManager();
+	return instance_;
+}
+
+void HidlManager::destroyInstance()
+{
+	if (instance_)
+		delete instance_;
+	instance_ = NULL;
+}
+
+int HidlManager::registerHidlService(struct wpa_global *global)
+{
+	// Create the main hidl service object and register with system
+	// ServiceManager.
+	supplicant_object_ = new Supplicant(global);
+
+	android::String16 service_name(hidl_constants::kServiceName);
+	android::defaultServiceManager()->addService(
+	    service_name, android::IInterface::asHidl(supplicant_object_));
+	return 0;
+}
+
+/**
+ * Register an interface to hidl manager.
+ *
+ * @param wpa_s |wpa_supplicant| struct corresponding to the interface.
+ *
+ * @return 0 on success, 1 on failure.
+ */
+int HidlManager::registerInterface(struct wpa_supplicant *wpa_s)
+{
+	if (!wpa_s)
+		return 1;
+
+	// Using the corresponding ifname as key to our object map.
+	const std::string ifname(wpa_s->ifname);
+
+	// Return failure if we already have an object for that |ifname|.
+	if (iface_object_map_.find(ifname) != iface_object_map_.end())
+		return 1;
+
+	iface_object_map_[ifname] = new Iface(wpa_s->global, wpa_s->ifname);
+	if (!iface_object_map_[ifname].get())
+		return 1;
+
+	// Initialize the vector of callbacks for this object.
+	iface_callbacks_map_[ifname] =
+	    std::vector<android::sp<fi::w1::wpa_supplicant::IIfaceCallback>>();
+
+	// Invoke the |OnInterfaceCreated| method on all registered callbacks.
+	callWithEachSupplicantCallback(std::bind(
+	    &fi::w1::wpa_supplicant::ISupplicantCallback::OnInterfaceCreated,
+	    std::placeholders::_1, ifname));
+	return 0;
+}
+
+/**
+ * Unregister an interface from hidl manager.
+ *
+ * @param wpa_s |wpa_supplicant| struct corresponding to the interface.
+ *
+ * @return 0 on success, 1 on failure.
+ */
+int HidlManager::unregisterInterface(struct wpa_supplicant *wpa_s)
+{
+	if (!wpa_s)
+		return 1;
+
+	const std::string ifname(wpa_s->ifname);
+
+	if (iface_object_map_.find(ifname) == iface_object_map_.end())
+		return 1;
+
+	// Delete the corresponding iface object from our map.
+	iface_object_map_.erase(ifname);
+
+	// Delete all callbacks registered for this object.
+	auto iface_callback_map_iter = iface_callbacks_map_.find(ifname);
+	if (iface_callback_map_iter == iface_callbacks_map_.end())
+		return 1;
+	const auto &iface_callback_list = iface_callback_map_iter->second;
+	for (const auto &callback : iface_callback_list) {
+		if (android::IInterface::asHidl(callback)->unlinkToDeath(
+			nullptr, callback.get()) != android::OK) {
+			wpa_printf(
+			    MSG_ERROR,
+			    "Error deregistering for death notification for "
+			    "iface callback object");
+		}
+	}
+	iface_callbacks_map_.erase(iface_callback_map_iter);
+
+	// Invoke the |OnInterfaceRemoved| method on all registered callbacks.
+	callWithEachSupplicantCallback(std::bind(
+	    &fi::w1::wpa_supplicant::ISupplicantCallback::OnInterfaceRemoved,
+	    std::placeholders::_1, ifname));
+	return 0;
+}
+
+/**
+ * Register a network to hidl manager.
+ *
+ * @param wpa_s |wpa_supplicant| struct corresponding to the interface on which
+ * the network is added.
+ * @param ssid |wpa_ssid| struct corresponding to the network being added.
+ *
+ * @return 0 on success, 1 on failure.
+ */
+int HidlManager::registerNetwork(
+    struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid)
+{
+	if (!wpa_s || !ssid)
+		return 1;
+
+	// Generate the key to be used to lookup the network.
+	const std::string network_key =
+	    getNetworkObjectMapKey(wpa_s->ifname, ssid->id);
+
+	if (network_object_map_.find(network_key) != network_object_map_.end())
+		return 1;
+
+	network_object_map_[network_key] =
+	    new Network(wpa_s->global, wpa_s->ifname, ssid->id);
+	if (!network_object_map_[network_key].get())
+		return 1;
+
+	// Initialize the vector of callbacks for this object.
+	network_callbacks_map_[network_key] = std::vector<
+	    android::sp<fi::w1::wpa_supplicant::INetworkCallback>>();
+
+	// Invoke the |OnNetworkAdded| method on all registered callbacks.
+	callWithEachIfaceCallback(
+	    wpa_s->ifname,
+	    std::bind(
+		&fi::w1::wpa_supplicant::IIfaceCallback::OnNetworkAdded,
+		std::placeholders::_1, ssid->id));
+	return 0;
+}
+
+/**
+ * Unregister a network from hidl manager.
+ *
+ * @param wpa_s |wpa_supplicant| struct corresponding to the interface on which
+ * the network is added.
+ * @param ssid |wpa_ssid| struct corresponding to the network being added.
+ *
+ * @return 0 on success, 1 on failure.
+ */
+int HidlManager::unregisterNetwork(
+    struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid)
+{
+	if (!wpa_s || !ssid)
+		return 1;
+
+	// Generate the key to be used to lookup the network.
+	const std::string network_key =
+	    getNetworkObjectMapKey(wpa_s->ifname, ssid->id);
+
+	if (network_object_map_.find(network_key) == network_object_map_.end())
+		return 1;
+
+	// Delete the corresponding network object from our map.
+	network_object_map_.erase(network_key);
+
+	// Delete all callbacks registered for this object.
+	auto network_callback_map_iter =
+	    network_callbacks_map_.find(network_key);
+	if (network_callback_map_iter == network_callbacks_map_.end())
+		return 1;
+	const auto &network_callback_list = network_callback_map_iter->second;
+	for (const auto &callback : network_callback_list) {
+		if (android::IInterface::asHidl(callback)->unlinkToDeath(
+			nullptr, callback.get()) != android::OK) {
+			wpa_printf(
+			    MSG_ERROR,
+			    "Error deregistering for death "
+			    "notification for "
+			    "network callback object");
+		}
+	}
+	network_callbacks_map_.erase(network_callback_map_iter);
+
+	// Invoke the |OnNetworkRemoved| method on all registered callbacks.
+	callWithEachIfaceCallback(
+	    wpa_s->ifname,
+	    std::bind(
+		&fi::w1::wpa_supplicant::IIfaceCallback::OnNetworkRemoved,
+		std::placeholders::_1, ssid->id));
+	return 0;
+}
+
+/**
+ * Notify all listeners about any state changes on a particular interface.
+ *
+ * @param wpa_s |wpa_supplicant| struct corresponding to the interface on which
+ * the state change event occured.
+ */
+int HidlManager::notifyStateChange(struct wpa_supplicant *wpa_s)
+{
+	if (!wpa_s)
+		return 1;
+
+	const std::string ifname(wpa_s->ifname);
+	if (iface_object_map_.find(ifname) == iface_object_map_.end())
+		return 1;
+
+	// Invoke the |OnStateChanged| method on all registered callbacks.
+	int state = wpa_s->wpa_state;
+	std::vector<uint8_t> bssid(wpa_s->bssid, wpa_s->bssid + ETH_ALEN);
+	int network_id =
+	    fi::w1::wpa_supplicant::IIfaceCallback::NETWORK_ID_INVALID;
+	std::vector<uint8_t> ssid;
+	if (wpa_s->current_ssid) {
+		network_id = wpa_s->current_ssid->id;
+		ssid.assign(
+		    wpa_s->current_ssid->ssid,
+		    wpa_s->current_ssid->ssid + wpa_s->current_ssid->ssid_len);
+	}
+	callWithEachIfaceCallback(
+	    wpa_s->ifname,
+	    std::bind(
+		&fi::w1::wpa_supplicant::IIfaceCallback::OnStateChanged,
+		std::placeholders::_1, state, bssid, network_id, ssid));
+	return 0;
+}
+
+/**
+ * Notify all listeners about a request on a particular network.
+ *
+ * @param wpa_s |wpa_supplicant| struct corresponding to the interface on which
+ * the network is present.
+ * @param ssid |wpa_ssid| struct corresponding to the network.
+ * @param type type of request.
+ * @param param addition params associated with the request.
+ */
+int HidlManager::notifyNetworkRequest(
+    struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid, int type,
+    const char *param)
+{
+	if (!wpa_s || !ssid)
+		return 1;
+
+	const std::string network_key =
+	    getNetworkObjectMapKey(wpa_s->ifname, ssid->id);
+	if (network_object_map_.find(network_key) == network_object_map_.end())
+		return 1;
+
+	callWithEachNetworkCallback(
+	    wpa_s->ifname, ssid->id,
+	    std::bind(
+		&fi::w1::wpa_supplicant::INetworkCallback::OnNetworkRequest,
+		std::placeholders::_1, type, param));
+	return 0;
+}
+
+/**
+ * Retrieve the |IIface| hidl object reference using the provided
+ * ifname.
+ *
+ * @param ifname Name of the corresponding interface.
+ * @param iface_object Hidl reference corresponding to the iface.
+ *
+ * @return 0 on success, 1 on failure.
+ */
+int HidlManager::getIfaceHidlObjectByIfname(
+    const std::string &ifname,
+    android::sp<fi::w1::wpa_supplicant::IIface> *iface_object)
+{
+	if (ifname.empty() || !iface_object)
+		return 1;
+
+	auto iface_object_iter = iface_object_map_.find(ifname);
+	if (iface_object_iter == iface_object_map_.end())
+		return 1;
+
+	*iface_object = iface_object_iter->second;
+	return 0;
+}
+
+/**
+ * Retrieve the |INetwork| hidl object reference using the provided
+ * ifname and network_id.
+ *
+ * @param ifname Name of the corresponding interface.
+ * @param network_id ID of the corresponding network.
+ * @param network_object Hidl reference corresponding to the network.
+ *
+ * @return 0 on success, 1 on failure.
+ */
+int HidlManager::getNetworkHidlObjectByIfnameAndNetworkId(
+    const std::string &ifname, int network_id,
+    android::sp<fi::w1::wpa_supplicant::INetwork> *network_object)
+{
+	if (ifname.empty() || network_id < 0 || !network_object)
+		return 1;
+
+	// Generate the key to be used to lookup the network.
+	const std::string network_key =
+	    getNetworkObjectMapKey(ifname, network_id);
+
+	auto network_object_iter = network_object_map_.find(network_key);
+	if (network_object_iter == network_object_map_.end())
+		return 1;
+
+	*network_object = network_object_iter->second;
+	return 0;
+}
+
+/**
+ * Add a new |ISupplicantCallback| hidl object reference to our
+ * global callback list.
+ *
+ * @param callback Hidl reference of the |ISupplicantCallback| object.
+ *
+ * @return 0 on success, 1 on failure.
+ */
+int HidlManager::addSupplicantCallbackHidlObject(
+    const android::sp<fi::w1::wpa_supplicant::ISupplicantCallback> &callback)
+{
+	// Register for death notification before we add it to our list.
+	auto on_hidl_died_fctor = std::bind(
+	    &HidlManager::removeSupplicantCallbackHidlObject, this,
+	    std::placeholders::_1);
+	return registerForDeathAndAddCallbackHidlObjectToList<
+	    fi::w1::wpa_supplicant::ISupplicantCallback>(
+	    callback, on_hidl_died_fctor, supplicant_callbacks_);
+}
+/**
+ * Add a new |IIfaceCallback| hidl object reference to our
+ * interface callback list.
+ *
+ * @param ifname Name of the corresponding interface.
+ * @param callback Hidl reference of the |IIfaceCallback| object.
+ *
+ * @return 0 on success, 1 on failure.
+ */
+int HidlManager::addIfaceCallbackHidlObject(
+    const std::string &ifname,
+    const android::sp<fi::w1::wpa_supplicant::IIfaceCallback> &callback)
+{
+	if (ifname.empty())
+		return 1;
+
+	auto iface_callback_map_iter = iface_callbacks_map_.find(ifname);
+	if (iface_callback_map_iter == iface_callbacks_map_.end())
+		return 1;
+	auto &iface_callback_list = iface_callback_map_iter->second;
+
+	// Register for death notification before we add it to our list.
+	auto on_hidl_died_fctor = std::bind(
+	    &HidlManager::removeIfaceCallbackHidlObject, this, ifname,
+	    std::placeholders::_1);
+	return registerForDeathAndAddCallbackHidlObjectToList<
+	    fi::w1::wpa_supplicant::IIfaceCallback>(
+	    callback, on_hidl_died_fctor, iface_callback_list);
+}
+
+/**
+ * Add a new |INetworkCallback| hidl object reference to our
+ * network callback list.
+ *
+ * @param ifname Name of the corresponding interface.
+ * @param network_id ID of the corresponding network.
+ * @param callback Hidl reference of the |INetworkCallback| object.
+ *
+ * @return 0 on success, 1 on failure.
+ */
+int HidlManager::addNetworkCallbackHidlObject(
+    const std::string &ifname, int network_id,
+    const android::sp<fi::w1::wpa_supplicant::INetworkCallback> &callback)
+{
+	if (ifname.empty() || network_id < 0)
+		return 1;
+
+	// Generate the key to be used to lookup the network.
+	const std::string network_key =
+	    getNetworkObjectMapKey(ifname, network_id);
+	auto network_callback_map_iter =
+	    network_callbacks_map_.find(network_key);
+	if (network_callback_map_iter == network_callbacks_map_.end())
+		return 1;
+	auto &network_callback_list = network_callback_map_iter->second;
+
+	// Register for death notification before we add it to our list.
+	auto on_hidl_died_fctor = std::bind(
+	    &HidlManager::removeNetworkCallbackHidlObject, this, ifname,
+	    network_id, std::placeholders::_1);
+	return registerForDeathAndAddCallbackHidlObjectToList<
+	    fi::w1::wpa_supplicant::INetworkCallback>(
+	    callback, on_hidl_died_fctor, network_callback_list);
+}
+
+/**
+ * Creates a unique key for the network using the provided |ifname| and
+ * |network_id| to be used in the internal map of |INetwork| objects.
+ * This is of the form |ifname|_|network_id|. For ex: "wlan0_1".
+ *
+ * @param ifname Name of the corresponding interface.
+ * @param network_id ID of the corresponding network.
+ */
+const std::string HidlManager::getNetworkObjectMapKey(
+    const std::string &ifname, int network_id)
+{
+	return ifname + "_" + std::to_string(network_id);
+}
+
+/**
+ * Removes the provided |ISupplicantCallback| hidl object reference
+ * from our global callback list.
+ *
+ * @param callback Hidl reference of the |ISupplicantCallback| object.
+ */
+void HidlManager::removeSupplicantCallbackHidlObject(
+    const android::sp<fi::w1::wpa_supplicant::ISupplicantCallback> &callback)
+{
+	supplicant_callbacks_.erase(
+	    std::remove(
+		supplicant_callbacks_.begin(), supplicant_callbacks_.end(),
+		callback),
+	    supplicant_callbacks_.end());
+}
+
+/**
+ * Removes the provided |IIfaceCallback| hidl object reference from
+ * our interface callback list.
+ *
+ * @param ifname Name of the corresponding interface.
+ * @param callback Hidl reference of the |IIfaceCallback| object.
+ */
+void HidlManager::removeIfaceCallbackHidlObject(
+    const std::string &ifname,
+    const android::sp<fi::w1::wpa_supplicant::IIfaceCallback> &callback)
+{
+	if (ifname.empty())
+		return;
+
+	auto iface_callback_map_iter = iface_callbacks_map_.find(ifname);
+	if (iface_callback_map_iter == iface_callbacks_map_.end())
+		return;
+
+	auto &iface_callback_list = iface_callback_map_iter->second;
+	iface_callback_list.erase(
+	    std::remove(
+		iface_callback_list.begin(), iface_callback_list.end(),
+		callback),
+	    iface_callback_list.end());
+}
+
+/**
+ * Removes the provided |INetworkCallback| hidl object reference from
+ * our network callback list.
+ *
+ * @param ifname Name of the corresponding interface.
+ * @param network_id ID of the corresponding network.
+ * @param callback Hidl reference of the |INetworkCallback| object.
+ */
+void HidlManager::removeNetworkCallbackHidlObject(
+    const std::string &ifname, int network_id,
+    const android::sp<fi::w1::wpa_supplicant::INetworkCallback> &callback)
+{
+	if (ifname.empty() || network_id < 0)
+		return;
+
+	// Generate the key to be used to lookup the network.
+	const std::string network_key =
+	    getNetworkObjectMapKey(ifname, network_id);
+
+	auto network_callback_map_iter =
+	    network_callbacks_map_.find(network_key);
+	if (network_callback_map_iter == network_callbacks_map_.end())
+		return;
+
+	auto &network_callback_list = network_callback_map_iter->second;
+	network_callback_list.erase(
+	    std::remove(
+		network_callback_list.begin(), network_callback_list.end(),
+		callback),
+	    network_callback_list.end());
+}
+
+/**
+ * Add callback to the corresponding list after linking to death on the
+ * corresponding hidl object reference.
+ *
+ * @param callback Hidl reference of the |INetworkCallback| object.
+ *
+ * @return 0 on success, 1 on failure.
+ */
+template <class CallbackType>
+int HidlManager::registerForDeathAndAddCallbackHidlObjectToList(
+    const android::sp<CallbackType> &callback,
+    const std::function<void(const android::sp<CallbackType> &)>
+	&on_hidl_died_fctor,
+    std::vector<android::sp<CallbackType>> &callback_list)
+{
+	auto death_notifier = new CallbackObjectDeathNotifier<CallbackType>(
+	    callback, on_hidl_died_fctor);
+	// Use the |callback.get()| as cookie so that we don't need to
+	// store a reference to this |CallbackObjectDeathNotifier| instance
+	// to use in |unlinkToDeath| later.
+	// NOTE: This may cause an immediate callback if the object is already
+	// dead,
+	// so add it to the list before we register for callback!
+	callback_list.push_back(callback);
+	if (android::IInterface::asHidl(callback)->linkToDeath(
+		death_notifier, callback.get()) != android::OK) {
+		wpa_printf(
+		    MSG_ERROR,
+		    "Error registering for death notification for "
+		    "supplicant callback object");
+		callback_list.erase(
+		    std::remove(
+			callback_list.begin(), callback_list.end(), callback),
+		    callback_list.end());
+		return 1;
+	}
+	return 0;
+}
+
+/**
+ * Helper function to invoke the provided callback method on all the
+ * registered |ISupplicantCallback| callback hidl objects.
+ *
+ * @param method Pointer to the required hidl method from
+ * |ISupplicantCallback|.
+ */
+void HidlManager::callWithEachSupplicantCallback(
+    const std::function<android::hidl::Status(
+	android::sp<fi::w1::wpa_supplicant::ISupplicantCallback>)> &method)
+{
+	for (const auto &callback : supplicant_callbacks_) {
+		method(callback);
+	}
+}
+
+/**
+ * Helper fucntion to invoke the provided callback method on all the
+ * registered |IIfaceCallback| callback hidl objects for the specified
+ * |ifname|.
+ *
+ * @param ifname Name of the corresponding interface.
+ * @param method Pointer to the required hidl method from |IIfaceCallback|.
+ */
+void HidlManager::callWithEachIfaceCallback(
+    const std::string &ifname,
+    const std::function<android::hidl::Status(
+	android::sp<fi::w1::wpa_supplicant::IIfaceCallback>)> &method)
+{
+	if (ifname.empty())
+		return;
+
+	auto iface_callback_map_iter = iface_callbacks_map_.find(ifname);
+	if (iface_callback_map_iter == iface_callbacks_map_.end())
+		return;
+	const auto &iface_callback_list = iface_callback_map_iter->second;
+	for (const auto &callback : iface_callback_list) {
+		method(callback);
+	}
+}
+
+/**
+ * Helper function to invoke the provided callback method on all the
+ * registered |INetworkCallback| callback hidl objects for the specified
+ * |ifname| & |network_id|.
+ *
+ * @param ifname Name of the corresponding interface.
+ * @param network_id ID of the corresponding network.
+ * @param method Pointer to the required hidl method from |INetworkCallback|.
+ */
+void HidlManager::callWithEachNetworkCallback(
+    const std::string &ifname, int network_id,
+    const std::function<android::hidl::Status(
+	android::sp<fi::w1::wpa_supplicant::INetworkCallback>)> &method)
+{
+	if (ifname.empty() || network_id < 0)
+		return;
+
+	// Generate the key to be used to lookup the network.
+	const std::string network_key =
+	    getNetworkObjectMapKey(ifname, network_id);
+	auto network_callback_map_iter =
+	    network_callbacks_map_.find(network_key);
+	if (network_callback_map_iter == network_callbacks_map_.end())
+		return;
+	const auto &network_callback_list = network_callback_map_iter->second;
+	for (const auto &callback : network_callback_list) {
+		method(callback);
+	}
+}
+}  // namespace wpa_supplicant_hidl
diff --git a/wpa_supplicant/hidl/hidl_manager.h b/wpa_supplicant/hidl/hidl_manager.h
new file mode 100644
index 0000000..f6178a4
--- /dev/null
+++ b/wpa_supplicant/hidl/hidl_manager.h
@@ -0,0 +1,267 @@
+/*
+ * 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_HIDL_MANAGER_H
+#define WPA_SUPPLICANT_HIDL_HIDL_MANAGER_H
+
+#include <map>
+#include <string>
+
+#include "fi/w1/wpa_supplicant/IIfaceCallback.h"
+#include "fi/w1/wpa_supplicant/INetworkCallback.h"
+#include "fi/w1/wpa_supplicant/ISupplicantCallback.h"
+
+#include "iface.h"
+#include "network.h"
+#include "supplicant.h"
+
+struct wpa_global;
+struct wpa_supplicant;
+
+namespace wpa_supplicant_hidl {
+
+/**
+ * HidlManager is responsible for managing the lifetime of all
+ * hidl objects created by wpa_supplicant. This is a singleton
+ * class which is created by the supplicant core and can be used
+ * to get references to the hidl objects.
+ */
+class HidlManager
+{
+public:
+	static HidlManager *getInstance();
+	static void destroyInstance();
+
+	// Methods called from wpa_supplicant core.
+	int registerHidlService(struct wpa_global *global);
+	int registerInterface(struct wpa_supplicant *wpa_s);
+	int unregisterInterface(struct wpa_supplicant *wpa_s);
+	int registerNetwork(
+	    struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid);
+	int unregisterNetwork(
+	    struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid);
+	int notifyStateChange(struct wpa_supplicant *wpa_s);
+	int notifyNetworkRequest(
+	    struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid, int type,
+	    const char *param);
+
+	// Methods called from hidl objects.
+	int getIfaceHidlObjectByIfname(
+	    const std::string &ifname,
+	    android::sp<fi::w1::wpa_supplicant::IIface> *iface_object);
+	int getNetworkHidlObjectByIfnameAndNetworkId(
+	    const std::string &ifname, int network_id,
+	    android::sp<fi::w1::wpa_supplicant::INetwork> *network_object);
+	int addSupplicantCallbackHidlObject(
+	    const android::sp<fi::w1::wpa_supplicant::ISupplicantCallback>
+		&callback);
+	int addIfaceCallbackHidlObject(
+	    const std::string &ifname,
+	    const android::sp<fi::w1::wpa_supplicant::IIfaceCallback>
+		&callback);
+	int addNetworkCallbackHidlObject(
+	    const std::string &ifname, int network_id,
+	    const android::sp<fi::w1::wpa_supplicant::INetworkCallback>
+		&callback);
+
+private:
+	HidlManager() = default;
+	~HidlManager() = default;
+	HidlManager(const HidlManager &) = default;
+	HidlManager &operator=(const HidlManager &) = default;
+
+	const std::string getNetworkObjectMapKey(
+	    const std::string &ifname, int network_id);
+
+	void removeSupplicantCallbackHidlObject(
+	    const android::sp<fi::w1::wpa_supplicant::ISupplicantCallback>
+		&callback);
+	void removeIfaceCallbackHidlObject(
+	    const std::string &ifname,
+	    const android::sp<fi::w1::wpa_supplicant::IIfaceCallback>
+		&callback);
+	void removeNetworkCallbackHidlObject(
+	    const std::string &ifname, int network_id,
+	    const android::sp<fi::w1::wpa_supplicant::INetworkCallback>
+		&callback);
+	template <class CallbackType>
+	int registerForDeathAndAddCallbackHidlObjectToList(
+	    const android::sp<CallbackType> &callback,
+	    const std::function<void(const android::sp<CallbackType> &)>
+		&on_hidl_died_fctor,
+	    std::vector<android::sp<CallbackType>> &callback_list);
+
+	void callWithEachSupplicantCallback(
+	    const std::function<android::hidl::Status(
+		android::sp<fi::w1::wpa_supplicant::ISupplicantCallback>)>
+		&method);
+	void callWithEachIfaceCallback(
+	    const std::string &ifname,
+	    const std::function<android::hidl::Status(
+		android::sp<fi::w1::wpa_supplicant::IIfaceCallback>)> &method);
+	void callWithEachNetworkCallback(
+	    const std::string &ifname, int network_id,
+	    const std::function<android::hidl::Status(
+		android::sp<fi::w1::wpa_supplicant::INetworkCallback>)>
+		&method);
+
+	// Singleton instance of this class.
+	static HidlManager *instance_;
+	// The main hidl service object.
+	android::sp<Supplicant> supplicant_object_;
+	// Map of all the interface specific hidl objects controlled by
+	// wpa_supplicant. This map is keyed in by the corresponding
+	// |ifname|.
+	std::map<const std::string, android::sp<Iface>> iface_object_map_;
+	// Map of all the network specific hidl objects controlled by
+	// wpa_supplicant. This map is keyed in by the corresponding
+	// |ifname| & |network_id|.
+	std::map<const std::string, android::sp<Network>> network_object_map_;
+
+	// Callback registered for the main hidl service object.
+	std::vector<android::sp<fi::w1::wpa_supplicant::ISupplicantCallback>>
+	    supplicant_callbacks_;
+	// Map of all the callbacks registered for interface specific
+	// hidl objects controlled by wpa_supplicant.  This map is keyed in by
+	// the corresponding |ifname|.
+	std::map<
+	    const std::string,
+	    std::vector<android::sp<fi::w1::wpa_supplicant::IIfaceCallback>>>
+	    iface_callbacks_map_;
+	// Map of all the callbacks registered for network specific
+	// hidl objects controlled by wpa_supplicant.  This map is keyed in by
+	// the corresponding |ifname| & |network_id|.
+	std::map<
+	    const std::string,
+	    std::vector<android::sp<fi::w1::wpa_supplicant::INetworkCallback>>>
+	    network_callbacks_map_;
+
+	/**
+	 * Helper class used to deregister the callback object reference from
+	 * our
+	 * callback list on the death of the hidl object.
+	 * This class stores a reference of the callback hidl object and a
+	 * function to be called to indicate the death of the hidl object.
+	 */
+	template <class CallbackType>
+	class CallbackObjectDeathNotifier
+	    : public android::IHidl::DeathRecipient
+	{
+	public:
+		CallbackObjectDeathNotifier(
+		    const android::sp<CallbackType> &callback,
+		    const std::function<void(const android::sp<CallbackType> &)>
+			&on_hidl_died)
+		    : callback_(callback), on_hidl_died_(on_hidl_died)
+		{
+		}
+		void hidlDied(
+		    const android::wp<android::IHidl> & /* who */) override
+		{
+			on_hidl_died_(callback_);
+		}
+
+	private:
+		// The callback hidl object reference.
+		const android::sp<CallbackType> callback_;
+		// Callback function to be called when the hidl dies.
+		const std::function<void(const android::sp<CallbackType> &)>
+		    on_hidl_died_;
+	};
+};
+
+// The hidl interface uses some values which are the same as internal ones to
+// avoid nasty runtime conversion functions. So, adding compile time asserts
+// to guard against any internal changes breaking the hidl interface.
+static_assert(
+    fi::w1::wpa_supplicant::INetwork::KEY_MGMT_MASK_NONE == WPA_KEY_MGMT_NONE,
+    "KeyMgmt value mismatch");
+static_assert(
+    fi::w1::wpa_supplicant::INetwork::KEY_MGMT_MASK_WPA_PSK == WPA_KEY_MGMT_PSK,
+    "KeyMgmt value mismatch");
+static_assert(
+    fi::w1::wpa_supplicant::INetwork::KEY_MGMT_MASK_WPA_EAP ==
+	WPA_KEY_MGMT_IEEE8021X,
+    "KeyMgmt value mismatch");
+static_assert(
+    fi::w1::wpa_supplicant::INetwork::KEY_MGMT_MASK_IEEE8021X ==
+	WPA_KEY_MGMT_IEEE8021X_NO_WPA,
+    "KeyMgmt value mismatch");
+static_assert(
+    fi::w1::wpa_supplicant::INetwork::PROTO_MASK_WPA == WPA_PROTO_WPA,
+    "Proto value mismatch");
+static_assert(
+    fi::w1::wpa_supplicant::INetwork::PROTO_MASK_RSN == WPA_PROTO_RSN,
+    "Proto value mismatch");
+static_assert(
+    fi::w1::wpa_supplicant::INetwork::PROTO_MASK_OSEN == WPA_PROTO_OSEN,
+    "Proto value mismatch");
+static_assert(
+    fi::w1::wpa_supplicant::INetwork::AUTH_ALG_MASK_OPEN == WPA_AUTH_ALG_OPEN,
+    "AuthAlg value mismatch");
+static_assert(
+    fi::w1::wpa_supplicant::INetwork::AUTH_ALG_MASK_SHARED ==
+	WPA_AUTH_ALG_SHARED,
+    "AuthAlg value mismatch");
+static_assert(
+    fi::w1::wpa_supplicant::INetwork::AUTH_ALG_MASK_LEAP == WPA_AUTH_ALG_LEAP,
+    "AuthAlg value mismatch");
+static_assert(
+    fi::w1::wpa_supplicant::INetwork::GROUP_CIPHER_MASK_WEP40 ==
+	WPA_CIPHER_WEP40,
+    "GroupCipher value mismatch");
+static_assert(
+    fi::w1::wpa_supplicant::INetwork::GROUP_CIPHER_MASK_WEP104 ==
+	WPA_CIPHER_WEP104,
+    "GroupCipher value mismatch");
+static_assert(
+    fi::w1::wpa_supplicant::INetwork::GROUP_CIPHER_MASK_TKIP == WPA_CIPHER_TKIP,
+    "GroupCipher value mismatch");
+static_assert(
+    fi::w1::wpa_supplicant::INetwork::GROUP_CIPHER_MASK_CCMP == WPA_CIPHER_CCMP,
+    "GroupCipher value mismatch");
+static_assert(
+    fi::w1::wpa_supplicant::INetwork::PAIRWISE_CIPHER_MASK_NONE ==
+	WPA_CIPHER_NONE,
+    "PairwiseCipher value mismatch");
+static_assert(
+    fi::w1::wpa_supplicant::INetwork::PAIRWISE_CIPHER_MASK_TKIP ==
+	WPA_CIPHER_TKIP,
+    "PairwiseCipher value mismatch");
+static_assert(
+    fi::w1::wpa_supplicant::INetwork::PAIRWISE_CIPHER_MASK_CCMP ==
+	WPA_CIPHER_CCMP,
+    "PairwiseCipher value mismatch");
+
+static_assert(
+    WPA_DISCONNECTED ==
+	fi::w1::wpa_supplicant::IIfaceCallback::STATE_DISCONNECTED,
+    "State value mismatch");
+static_assert(
+    WPA_COMPLETED == fi::w1::wpa_supplicant::IIfaceCallback::STATE_COMPLETED,
+    "State value mismatch");
+
+static_assert(
+    WPA_CTRL_REQ_UNKNOWN ==
+	fi::w1::wpa_supplicant::INetwork::NETWORK_RSP_UNKNOWN,
+    "Network Rsp value mismatch");
+static_assert(
+    WPA_CTRL_REQ_EXT_CERT_CHECK ==
+	fi::w1::wpa_supplicant::INetwork::NETWORK_RSP_EXT_CERT_CHECK,
+    "Network Rsp value mismatch");
+static_assert(
+    WPA_CTRL_REQ_UNKNOWN ==
+	fi::w1::wpa_supplicant::INetworkCallback::NETWORK_REQ_UNKNOWN,
+    "Network Req value mismatch");
+static_assert(
+    WPA_CTRL_REQ_EXT_CERT_CHECK ==
+	fi::w1::wpa_supplicant::INetworkCallback::NETWORK_REQ_EXT_CERT_CHECK,
+    "Network Req value mismatch");
+}  // namespace wpa_supplicant_hidl
+#endif  // WPA_SUPPLICANT_HIDL_HIDL_MANAGER_H
diff --git a/wpa_supplicant/hidl/iface.cpp b/wpa_supplicant/hidl/iface.cpp
new file mode 100644
index 0000000..1ba93b7
--- /dev/null
+++ b/wpa_supplicant/hidl/iface.cpp
@@ -0,0 +1,279 @@
+/*
+ * 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 "iface.h"
+
+namespace wpa_supplicant_hidl {
+
+#define RETURN_IF_IFACE_INVALID(wpa_s)                                  \
+	{                                                               \
+		if (!wpa_s) {                                           \
+			return android::hidl::Status::                \
+			    fromServiceSpecificError(                   \
+				ERROR_IFACE_INVALID,                    \
+				"wpa_supplicant does not control this " \
+				"interface.");                          \
+		}                                                       \
+	}  // #define RETURN_IF_IFACE_INVALID(wpa_s)
+
+Iface::Iface(struct wpa_global *wpa_global, const char ifname[])
+    : wpa_global_(wpa_global), ifname_(ifname)
+{
+}
+
+android::hidl::Status Iface::GetName(std::string *iface_name_out)
+{
+	// We could directly return the name we hold, but let's verify
+	// if the underlying iface still exists.
+	RETURN_IF_IFACE_INVALID(retrieveIfacePtr());
+	*iface_name_out = ifname_;
+	return android::hidl::Status::ok();
+}
+
+android::hidl::Status Iface::AddNetwork(
+    android::sp<fi::w1::wpa_supplicant::INetwork> *network_object_out)
+{
+	struct wpa_supplicant *wpa_s = retrieveIfacePtr();
+	RETURN_IF_IFACE_INVALID(wpa_s);
+
+	struct wpa_ssid *ssid = wpa_supplicant_add_network(wpa_s);
+	if (!ssid) {
+		return android::hidl::Status::fromServiceSpecificError(
+		    ERROR_GENERIC, "wpa_supplicant couldn't add this network.");
+	}
+
+	HidlManager *hidl_manager = HidlManager::getInstance();
+	if (!hidl_manager ||
+	    hidl_manager->getNetworkHidlObjectByIfnameAndNetworkId(
+		wpa_s->ifname, ssid->id, network_object_out)) {
+		return android::hidl::Status::fromServiceSpecificError(
+		    ERROR_GENERIC,
+		    "wpa_supplicant encountered a hidl error.");
+	}
+	return android::hidl::Status::ok();
+}
+
+android::hidl::Status Iface::RemoveNetwork(int network_id)
+{
+	struct wpa_supplicant *wpa_s = retrieveIfacePtr();
+	RETURN_IF_IFACE_INVALID(wpa_s);
+
+	int result = wpa_supplicant_remove_network(wpa_s, network_id);
+	if (result == -1) {
+		return android::hidl::Status::fromServiceSpecificError(
+		    ERROR_NETWORK_UNKNOWN,
+		    "wpa_supplicant does not control this network.");
+	}
+
+	if (result == -2) {
+		return android::hidl::Status::fromServiceSpecificError(
+		    ERROR_GENERIC,
+		    "wpa_supplicant couldn't remove this network.");
+	}
+	return android::hidl::Status::ok();
+}
+
+android::hidl::Status Iface::GetNetwork(
+    int network_id,
+    android::sp<fi::w1::wpa_supplicant::INetwork> *network_object_out)
+{
+	struct wpa_supplicant *wpa_s = retrieveIfacePtr();
+	RETURN_IF_IFACE_INVALID(wpa_s);
+
+	struct wpa_ssid *ssid = wpa_config_get_network(wpa_s->conf, network_id);
+	if (!ssid) {
+		return android::hidl::Status::fromServiceSpecificError(
+		    ERROR_NETWORK_UNKNOWN,
+		    "wpa_supplicant does not control this network.");
+	}
+
+	HidlManager *hidl_manager = HidlManager::getInstance();
+	if (!hidl_manager ||
+	    hidl_manager->getNetworkHidlObjectByIfnameAndNetworkId(
+		wpa_s->ifname, ssid->id, network_object_out)) {
+		return android::hidl::Status::fromServiceSpecificError(
+		    ERROR_GENERIC,
+		    "wpa_supplicant encountered a hidl error.");
+	}
+	return android::hidl::Status::ok();
+}
+
+android::hidl::Status Iface::RegisterCallback(
+    const android::sp<fi::w1::wpa_supplicant::IIfaceCallback> &callback)
+{
+	struct wpa_supplicant *wpa_s = retrieveIfacePtr();
+	RETURN_IF_IFACE_INVALID(wpa_s);
+
+	HidlManager *hidl_manager = HidlManager::getInstance();
+	if (!hidl_manager ||
+	    hidl_manager->addIfaceCallbackHidlObject(ifname_, callback)) {
+		return android::hidl::Status::fromServiceSpecificError(
+		    ERROR_GENERIC,
+		    "wpa_supplicant encountered a hidl error.");
+	}
+	return android::hidl::Status::ok();
+}
+
+android::hidl::Status Iface::Reassociate()
+{
+	struct wpa_supplicant *wpa_s = retrieveIfacePtr();
+	RETURN_IF_IFACE_INVALID(wpa_s);
+
+	if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED) {
+		return android::hidl::Status::fromServiceSpecificError(
+		    ERROR_IFACE_DISABLED);
+	}
+	wpas_request_connection(wpa_s);
+	return android::hidl::Status::ok();
+}
+
+android::hidl::Status Iface::Reconnect()
+{
+	struct wpa_supplicant *wpa_s = retrieveIfacePtr();
+	RETURN_IF_IFACE_INVALID(wpa_s);
+
+	if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED) {
+		return android::hidl::Status::fromServiceSpecificError(
+		    ERROR_IFACE_DISABLED);
+	}
+	if (!wpa_s->disconnected) {
+		return android::hidl::Status::fromServiceSpecificError(
+		    ERROR_IFACE_NOT_DISCONNECTED);
+	}
+	wpas_request_connection(wpa_s);
+	return android::hidl::Status::ok();
+}
+
+android::hidl::Status Iface::Disconnect()
+{
+	struct wpa_supplicant *wpa_s = retrieveIfacePtr();
+	RETURN_IF_IFACE_INVALID(wpa_s);
+
+	if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED) {
+		return android::hidl::Status::fromServiceSpecificError(
+		    ERROR_IFACE_DISABLED);
+	}
+	wpas_request_disconnection(wpa_s);
+	return android::hidl::Status::ok();
+}
+
+android::hidl::Status Iface::SetPowerSave(bool enable)
+{
+	struct wpa_supplicant *wpa_s = retrieveIfacePtr();
+	RETURN_IF_IFACE_INVALID(wpa_s);
+	if (wpa_drv_set_p2p_powersave(wpa_s, enable, -1, -1)) {
+		const std::string error_msg = "Failed setting power save mode" +
+					      std::to_string(enable) + ".";
+		return android::hidl::Status::fromServiceSpecificError(
+		    ERROR_GENERIC, error_msg.c_str());
+	}
+	return android::hidl::Status::ok();
+}
+
+android::hidl::Status Iface::InitiateTDLSDiscover(
+    const std::vector<uint8_t> &mac_address)
+{
+	struct wpa_supplicant *wpa_s = retrieveIfacePtr();
+	RETURN_IF_IFACE_INVALID(wpa_s);
+
+	if (mac_address.size() != MAC_ADDRESS_LEN) {
+		const std::string error_msg =
+		    "Invalid MAC address value length: " +
+		    std::to_string(mac_address.size()) + ".";
+		return android::hidl::Status::fromExceptionCode(
+		    android::hidl::Status::EX_ILLEGAL_ARGUMENT,
+		    error_msg.c_str());
+	}
+	int ret;
+	const u8 *peer = mac_address.data();
+	if (wpa_tdls_is_external_setup(wpa_s->wpa)) {
+		ret = wpa_tdls_send_discovery_request(wpa_s->wpa, peer);
+	} else {
+		ret = wpa_drv_tdls_oper(wpa_s, TDLS_DISCOVERY_REQ, peer);
+	}
+	if (ret) {
+		return android::hidl::Status::fromServiceSpecificError(
+		    ERROR_GENERIC, "Failed to initiate TDLS Discover.");
+	}
+	return android::hidl::Status::ok();
+}
+
+android::hidl::Status Iface::InitiateTDLSSetup(
+    const std::vector<uint8_t> &mac_address)
+{
+	struct wpa_supplicant *wpa_s = retrieveIfacePtr();
+	RETURN_IF_IFACE_INVALID(wpa_s);
+
+	if (mac_address.size() != MAC_ADDRESS_LEN) {
+		const std::string error_msg =
+		    "Invalid MAC address value length: " +
+		    std::to_string(mac_address.size()) + ".";
+		return android::hidl::Status::fromExceptionCode(
+		    android::hidl::Status::EX_ILLEGAL_ARGUMENT,
+		    error_msg.c_str());
+	}
+	int ret;
+	const u8 *peer = mac_address.data();
+	if (wpa_tdls_is_external_setup(wpa_s->wpa) &&
+	    !(wpa_s->conf->tdls_external_control)) {
+		wpa_tdls_remove(wpa_s->wpa, peer);
+		ret = wpa_tdls_start(wpa_s->wpa, peer);
+	} else {
+		ret = wpa_drv_tdls_oper(wpa_s, TDLS_SETUP, peer);
+	}
+	if (ret) {
+		return android::hidl::Status::fromServiceSpecificError(
+		    ERROR_GENERIC, "Failed to initiate TDLS Setup.");
+	}
+	return android::hidl::Status::ok();
+}
+
+android::hidl::Status Iface::InitiateTDLSTeardown(
+    const std::vector<uint8_t> &mac_address)
+{
+	struct wpa_supplicant *wpa_s = retrieveIfacePtr();
+	RETURN_IF_IFACE_INVALID(wpa_s);
+
+	if (mac_address.size() != MAC_ADDRESS_LEN) {
+		const std::string error_msg =
+		    "Invalid MAC address value length: " +
+		    std::to_string(mac_address.size()) + ".";
+		return android::hidl::Status::fromExceptionCode(
+		    android::hidl::Status::EX_ILLEGAL_ARGUMENT,
+		    error_msg.c_str());
+	}
+	int ret;
+	const u8 *peer = mac_address.data();
+	if (wpa_tdls_is_external_setup(wpa_s->wpa) &&
+	    !(wpa_s->conf->tdls_external_control)) {
+		ret = wpa_tdls_teardown_link(
+		    wpa_s->wpa, peer, WLAN_REASON_TDLS_TEARDOWN_UNSPECIFIED);
+	} else {
+		ret = wpa_drv_tdls_oper(wpa_s, TDLS_TEARDOWN, peer);
+	}
+	if (ret) {
+		return android::hidl::Status::fromServiceSpecificError(
+		    ERROR_GENERIC, "Failed to initiate TDLS Teardown.");
+	}
+	return android::hidl::Status::ok();
+}
+
+/**
+ * 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 *Iface::retrieveIfacePtr()
+{
+	return wpa_supplicant_get_iface(
+	    (struct wpa_global *)wpa_global_, ifname_.c_str());
+}
+}  // namespace wpa_supplicant_hidl
diff --git a/wpa_supplicant/hidl/iface.h b/wpa_supplicant/hidl/iface.h
new file mode 100644
index 0000000..51d7f39
--- /dev/null
+++ b/wpa_supplicant/hidl/iface.h
@@ -0,0 +1,76 @@
+/*
+ * 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_IFACE_H
+#define WPA_SUPPLICANT_HIDL_IFACE_H
+
+#include <android-base/macros.h>
+
+#include "fi/w1/wpa_supplicant/BnIface.h"
+#include "fi/w1/wpa_supplicant/INetwork.h"
+
+extern "C" {
+#include "utils/common.h"
+#include "utils/includes.h"
+#include "wpa_supplicant_i.h"
+#include "driver_i.h"
+}
+
+namespace wpa_supplicant_hidl {
+
+/**
+ * Implementation of Iface hidl object. Each unique hidl
+ * object is used for control operations on a specific interface
+ * controlled by wpa_supplicant.
+ */
+class Iface : public fi::w1::wpa_supplicant::BnIface
+{
+public:
+	Iface(struct wpa_global *wpa_global, const char ifname[]);
+	~Iface() override = default;
+
+	// Hidl methods exposed in aidl.
+	android::hidl::Status GetName(std::string *iface_name_out) override;
+	android::hidl::Status AddNetwork(
+	    android::sp<fi::w1::wpa_supplicant::INetwork> *network_object_out)
+	    override;
+	android::hidl::Status RemoveNetwork(int network_id) override;
+	android::hidl::Status GetNetwork(
+	    int network_id,
+	    android::sp<fi::w1::wpa_supplicant::INetwork> *network_object_out)
+	    override;
+	android::hidl::Status RegisterCallback(
+	    const android::sp<fi::w1::wpa_supplicant::IIfaceCallback> &callback)
+	    override;
+	android::hidl::Status Reassociate() override;
+	android::hidl::Status Reconnect() override;
+	android::hidl::Status Disconnect() override;
+	android::hidl::Status SetPowerSave(bool enable) override;
+	android::hidl::Status InitiateTDLSDiscover(
+	    const std::vector<uint8_t> &mac_address) override;
+	android::hidl::Status InitiateTDLSSetup(
+	    const std::vector<uint8_t> &mac_address) override;
+	android::hidl::Status InitiateTDLSTeardown(
+	    const std::vector<uint8_t> &mac_address) override;
+
+private:
+	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 hidl object controls
+	const std::string ifname_;
+
+	DISALLOW_COPY_AND_ASSIGN(Iface);
+};
+
+}  // namespace wpa_supplicant_hidl
+
+#endif  // WPA_SUPPLICANT_HIDL_IFACE_H
diff --git a/wpa_supplicant/hidl/network.cpp b/wpa_supplicant/hidl/network.cpp
new file mode 100644
index 0000000..97a7368
--- /dev/null
+++ b/wpa_supplicant/hidl/network.cpp
@@ -0,0 +1,932 @@
+/*
+ * 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 "network.h"
+
+namespace {
+constexpr int kAllowedKeyMgmtMask =
+    (fi::w1::wpa_supplicant::INetwork::KEY_MGMT_MASK_NONE |
+     fi::w1::wpa_supplicant::INetwork::KEY_MGMT_MASK_WPA_PSK |
+     fi::w1::wpa_supplicant::INetwork::KEY_MGMT_MASK_WPA_EAP |
+     fi::w1::wpa_supplicant::INetwork::KEY_MGMT_MASK_IEEE8021X);
+constexpr int kAllowedProtoMask =
+    (fi::w1::wpa_supplicant::INetwork::PROTO_MASK_WPA |
+     fi::w1::wpa_supplicant::INetwork::PROTO_MASK_RSN |
+     fi::w1::wpa_supplicant::INetwork::PROTO_MASK_OSEN);
+constexpr int kAllowedAuthAlgMask =
+    (fi::w1::wpa_supplicant::INetwork::AUTH_ALG_MASK_OPEN |
+     fi::w1::wpa_supplicant::INetwork::AUTH_ALG_MASK_SHARED |
+     fi::w1::wpa_supplicant::INetwork::AUTH_ALG_MASK_LEAP);
+constexpr int kAllowedGroupCipherMask =
+    (fi::w1::wpa_supplicant::INetwork::GROUP_CIPHER_MASK_WEP40 |
+     fi::w1::wpa_supplicant::INetwork::GROUP_CIPHER_MASK_WEP104 |
+     fi::w1::wpa_supplicant::INetwork::GROUP_CIPHER_MASK_TKIP |
+     fi::w1::wpa_supplicant::INetwork::GROUP_CIPHER_MASK_CCMP);
+constexpr int kAllowedPairwiseCipherMask =
+    (fi::w1::wpa_supplicant::INetwork::PAIRWISE_CIPHER_MASK_NONE |
+     fi::w1::wpa_supplicant::INetwork::PAIRWISE_CIPHER_MASK_TKIP |
+     fi::w1::wpa_supplicant::INetwork::PAIRWISE_CIPHER_MASK_CCMP);
+
+constexpr int kEapMethodMax =
+    fi::w1::wpa_supplicant::INetwork::EAP_METHOD_WFA_UNAUTH_TLS + 1;
+constexpr int kEapMethodMin = fi::w1::wpa_supplicant::INetwork::EAP_METHOD_PEAP;
+constexpr char const *kEapMethodStrings[kEapMethodMax] = {
+    "PEAP", "TLS", "TTLS", "PWD", "SIM", "AKA", "AKA'", "WFA-UNAUTH-TLS"};
+
+constexpr int kEapPhase2MethodMax =
+    fi::w1::wpa_supplicant::INetwork::EAP_PHASE2_METHOD_GTC + 1;
+constexpr int kEapPhase2MethodMin =
+    fi::w1::wpa_supplicant::INetwork::EAP_PHASE2_METHOD_NONE;
+constexpr char const *kEapPhase2MethodStrings[kEapPhase2MethodMax] = {
+    "NULL", "PAP", "MSCHAP", "MSCHAPV2", "GTC"};
+}  // namespace
+
+namespace wpa_supplicant_hidl {
+
+#define RETURN_IF_NETWORK_INVALID(wpa_ssid)                             \
+	{                                                               \
+		if (!wpa_ssid) {                                        \
+			return android::hidl::Status::                \
+			    fromServiceSpecificError(                   \
+				ERROR_NETWORK_INVALID,                  \
+				"wpa_supplicant does not control this " \
+				"network.");                            \
+		}                                                       \
+	}  // #define RETURN_IF_NETWORK_INVALID(wpa_ssid)
+
+Network::Network(
+    struct wpa_global *wpa_global, const char ifname[], int network_id)
+    : wpa_global_(wpa_global), ifname_(ifname), network_id_(network_id)
+{
+}
+
+android::hidl::Status Network::GetId(int *network_id_out)
+{
+	RETURN_IF_NETWORK_INVALID(retrieveNetworkPtr());
+	*network_id_out = network_id_;
+	return android::hidl::Status::ok();
+}
+
+android::hidl::Status Network::GetInterfaceName(std::string *ifname_out)
+{
+	RETURN_IF_NETWORK_INVALID(retrieveNetworkPtr());
+	*ifname_out = ifname_;
+	return android::hidl::Status::ok();
+}
+
+android::hidl::Status Network::RegisterCallback(
+    const android::sp<fi::w1::wpa_supplicant::INetworkCallback> &callback)
+{
+	RETURN_IF_NETWORK_INVALID(retrieveNetworkPtr());
+	HidlManager *hidl_manager = HidlManager::getInstance();
+	if (!hidl_manager ||
+	    hidl_manager->addNetworkCallbackHidlObject(
+		ifname_, network_id_, callback)) {
+		return android::hidl::Status::fromServiceSpecificError(
+		    ERROR_GENERIC,
+		    "wpa_supplicant encountered a hidl error.");
+	}
+	return android::hidl::Status::ok();
+}
+
+android::hidl::Status Network::SetSSID(const std::vector<uint8_t> &ssid)
+{
+	struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
+	RETURN_IF_NETWORK_INVALID(wpa_ssid);
+
+	if (ssid.empty() || ssid.size() > SSID_MAX_LEN) {
+		const std::string error_msg = "Invalid SSID value length: " +
+					      std::to_string(ssid.size()) + ".";
+		return android::hidl::Status::fromExceptionCode(
+		    android::hidl::Status::EX_ILLEGAL_ARGUMENT,
+		    error_msg.c_str());
+	}
+	android::hidl::Status status = setByteArrayFieldAndResetState(
+	    ssid.data(), ssid.size(), &(wpa_ssid->ssid), &(wpa_ssid->ssid_len),
+	    "ssid");
+	if (status.isOk() && wpa_ssid->passphrase) {
+		wpa_config_update_psk(wpa_ssid);
+	}
+	return status;
+}
+
+android::hidl::Status Network::SetBSSID(const std::vector<uint8_t> &bssid)
+{
+	struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
+	RETURN_IF_NETWORK_INVALID(wpa_ssid);
+
+	if (!bssid.empty() && bssid.size() != BSSID_LEN) {
+		const std::string error_msg = "Invalid BSSID value length: " +
+					      std::to_string(bssid.size()) +
+					      ".";
+		return android::hidl::Status::fromExceptionCode(
+		    android::hidl::Status::EX_ILLEGAL_ARGUMENT,
+		    error_msg.c_str());
+	}
+	int prev_bssid_set = wpa_ssid->bssid_set;
+	u8 prev_bssid[ETH_ALEN];
+	os_memcpy(prev_bssid, wpa_ssid->bssid, ETH_ALEN);
+	// Empty array is used to clear out the BSSID value.
+	if (bssid.empty()) {
+		wpa_ssid->bssid_set = 0;
+		wpa_printf(MSG_MSGDUMP, "BSSID any");
+	} else {
+		os_memcpy(wpa_ssid->bssid, bssid.data(), ETH_ALEN);
+		wpa_ssid->bssid_set = 1;
+		wpa_hexdump(MSG_MSGDUMP, "BSSID", wpa_ssid->bssid, ETH_ALEN);
+	}
+	struct wpa_supplicant *wpa_s = retrieveIfacePtr();
+	if ((wpa_ssid->bssid_set != prev_bssid_set ||
+	     os_memcmp(wpa_ssid->bssid, prev_bssid, ETH_ALEN) != 0)) {
+		wpas_notify_network_bssid_set_changed(wpa_s, wpa_ssid);
+	}
+	return android::hidl::Status::ok();
+}
+
+android::hidl::Status Network::SetScanSSID(bool enable)
+{
+	struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
+	RETURN_IF_NETWORK_INVALID(wpa_ssid);
+
+	wpa_ssid->scan_ssid = enable ? 1 : 0;
+	resetInternalStateAfterParamsUpdate();
+	return android::hidl::Status::ok();
+}
+
+android::hidl::Status Network::SetKeyMgmt(int32_t key_mgmt_mask)
+{
+	struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
+	RETURN_IF_NETWORK_INVALID(wpa_ssid);
+
+	if (key_mgmt_mask & ~kAllowedKeyMgmtMask) {
+		const std::string error_msg = "Invalid key_mgmt value: " +
+					      std::to_string(key_mgmt_mask) +
+					      ".";
+		return android::hidl::Status::fromExceptionCode(
+		    android::hidl::Status::EX_ILLEGAL_ARGUMENT,
+		    error_msg.c_str());
+	}
+	wpa_ssid->key_mgmt = key_mgmt_mask;
+	wpa_printf(MSG_MSGDUMP, "key_mgmt: 0x%x", wpa_ssid->key_mgmt);
+	resetInternalStateAfterParamsUpdate();
+	return android::hidl::Status::ok();
+}
+
+android::hidl::Status Network::SetProto(int32_t proto_mask)
+{
+	struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
+	RETURN_IF_NETWORK_INVALID(wpa_ssid);
+
+	if (proto_mask & ~kAllowedProtoMask) {
+		const std::string error_msg =
+		    "Invalid proto value: " + std::to_string(proto_mask) + ".";
+		return android::hidl::Status::fromExceptionCode(
+		    android::hidl::Status::EX_ILLEGAL_ARGUMENT,
+		    error_msg.c_str());
+	}
+	wpa_ssid->proto = proto_mask;
+	wpa_printf(MSG_MSGDUMP, "proto: 0x%x", wpa_ssid->proto);
+	resetInternalStateAfterParamsUpdate();
+	return android::hidl::Status::ok();
+}
+
+android::hidl::Status Network::SetAuthAlg(int32_t auth_alg_mask)
+{
+	struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
+	RETURN_IF_NETWORK_INVALID(wpa_ssid);
+
+	if (auth_alg_mask & ~kAllowedAuthAlgMask) {
+		const std::string error_msg = "Invalid auth_alg value: " +
+					      std::to_string(auth_alg_mask) +
+					      ".";
+		return android::hidl::Status::fromExceptionCode(
+		    android::hidl::Status::EX_ILLEGAL_ARGUMENT,
+		    error_msg.c_str());
+	}
+	wpa_ssid->auth_alg = auth_alg_mask;
+	wpa_printf(MSG_MSGDUMP, "auth_alg: 0x%x", wpa_ssid->auth_alg);
+	resetInternalStateAfterParamsUpdate();
+	return android::hidl::Status::ok();
+}
+
+android::hidl::Status Network::SetGroupCipher(int32_t group_cipher_mask)
+{
+	struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
+	RETURN_IF_NETWORK_INVALID(wpa_ssid);
+
+	if (group_cipher_mask & ~kAllowedGroupCipherMask) {
+		const std::string error_msg =
+		    "Invalid group_cipher value: " +
+		    std::to_string(group_cipher_mask) + ".";
+		return android::hidl::Status::fromExceptionCode(
+		    android::hidl::Status::EX_ILLEGAL_ARGUMENT,
+		    error_msg.c_str());
+	}
+	wpa_ssid->group_cipher = group_cipher_mask;
+	wpa_printf(MSG_MSGDUMP, "group_cipher: 0x%x", wpa_ssid->group_cipher);
+	resetInternalStateAfterParamsUpdate();
+	return android::hidl::Status::ok();
+}
+
+android::hidl::Status Network::SetPairwiseCipher(int32_t pairwise_cipher_mask)
+{
+	struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
+	RETURN_IF_NETWORK_INVALID(wpa_ssid);
+
+	if (pairwise_cipher_mask & ~kAllowedPairwiseCipherMask) {
+		const std::string error_msg =
+		    "Invalid pairwise_cipher value: " +
+		    std::to_string(pairwise_cipher_mask) + ".";
+		return android::hidl::Status::fromExceptionCode(
+		    android::hidl::Status::EX_ILLEGAL_ARGUMENT,
+		    error_msg.c_str());
+	}
+	wpa_ssid->pairwise_cipher = pairwise_cipher_mask;
+	wpa_printf(
+	    MSG_MSGDUMP, "pairwise_cipher: 0x%x", wpa_ssid->pairwise_cipher);
+	resetInternalStateAfterParamsUpdate();
+	return android::hidl::Status::ok();
+}
+
+android::hidl::Status Network::SetPskPassphrase(const std::string &psk)
+{
+	struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
+	RETURN_IF_NETWORK_INVALID(wpa_ssid);
+
+	if (isPskPassphraseValid(psk)) {
+		return android::hidl::Status::fromExceptionCode(
+		    android::hidl::Status::EX_ILLEGAL_ARGUMENT,
+		    "Invalid Psk passphrase value.");
+	}
+	if (wpa_ssid->passphrase &&
+	    os_strlen(wpa_ssid->passphrase) == psk.size() &&
+	    os_memcmp(wpa_ssid->passphrase, psk.c_str(), psk.size()) == 0) {
+		return android::hidl::Status::ok();
+	}
+	// Flag to indicate if raw psk is calculated or not using
+	// |wpa_config_update_psk|. Deferred if ssid not already set.
+	wpa_ssid->psk_set = 0;
+	android::hidl::Status status = setStringKeyFieldAndResetState(
+	    psk.data(), &(wpa_ssid->passphrase), "psk passphrase");
+	if (status.isOk() && wpa_ssid->ssid_len) {
+		wpa_config_update_psk(wpa_ssid);
+	}
+	return status;
+}
+
+android::hidl::Status Network::SetWepKey(
+    int key_idx, const std::vector<uint8_t> &wep_key)
+{
+	struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
+	RETURN_IF_NETWORK_INVALID(wpa_ssid);
+
+	if (key_idx < 0 || key_idx >= WEP_KEYS_MAX_NUM) {
+		const std::string error_msg =
+		    "Invalid Wep Key index: " + std::to_string(key_idx) + ".";
+		return android::hidl::Status::fromExceptionCode(
+		    android::hidl::Status::EX_ILLEGAL_ARGUMENT,
+		    error_msg.c_str());
+	}
+	if (wep_key.size() != WEP40_KEY_LEN &&
+	    wep_key.size() != WEP104_KEY_LEN) {
+		const std::string error_msg = "Invalid Wep Key value length: " +
+					      std::to_string(wep_key.size()) +
+					      ".";
+		return android::hidl::Status::fromExceptionCode(
+		    android::hidl::Status::EX_ILLEGAL_ARGUMENT,
+		    error_msg.c_str());
+	}
+	os_memcpy(wpa_ssid->wep_key[key_idx], wep_key.data(), wep_key.size());
+	wpa_ssid->wep_key_len[key_idx] = wep_key.size();
+	std::string msg_dump_title("wep_key" + std::to_string(key_idx));
+	wpa_hexdump_key(
+	    MSG_MSGDUMP, msg_dump_title.c_str(), wpa_ssid->wep_key[key_idx],
+	    wpa_ssid->wep_key_len[key_idx]);
+	resetInternalStateAfterParamsUpdate();
+	return android::hidl::Status::ok();
+}
+
+android::hidl::Status Network::SetWepTxKeyIdx(int32_t wep_tx_key_idx)
+{
+	struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
+	RETURN_IF_NETWORK_INVALID(wpa_ssid);
+
+	if (wep_tx_key_idx < 0 || wep_tx_key_idx >= WEP_KEYS_MAX_NUM) {
+		const std::string error_msg = "Invalid Wep Key index: " +
+					      std::to_string(wep_tx_key_idx) +
+					      ".";
+		return android::hidl::Status::fromExceptionCode(
+		    android::hidl::Status::EX_ILLEGAL_ARGUMENT,
+		    error_msg.c_str());
+	}
+	wpa_ssid->wep_tx_keyidx = wep_tx_key_idx;
+	resetInternalStateAfterParamsUpdate();
+	return android::hidl::Status::ok();
+}
+
+android::hidl::Status Network::SetRequirePMF(bool enable)
+{
+	struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
+	RETURN_IF_NETWORK_INVALID(wpa_ssid);
+
+	wpa_ssid->ieee80211w =
+	    enable ? MGMT_FRAME_PROTECTION_REQUIRED : NO_MGMT_FRAME_PROTECTION;
+	resetInternalStateAfterParamsUpdate();
+	return android::hidl::Status::ok();
+}
+
+android::hidl::Status Network::SetEapMethod(int32_t method)
+{
+	struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
+	RETURN_IF_NETWORK_INVALID(wpa_ssid);
+	int retrieved_vendor, retrieved_method;
+
+	if (method < kEapMethodMin || method >= kEapMethodMax) {
+		const std::string error_msg =
+		    "Invalid EAP method: " + std::to_string(method) + ".";
+		return android::hidl::Status::fromExceptionCode(
+		    android::hidl::Status::EX_ILLEGAL_ARGUMENT,
+		    error_msg.c_str());
+	}
+	const char *method_str = kEapMethodStrings[method];
+	// This string lookup is needed to check if the device supports the
+	// corresponding EAP type.
+	retrieved_method = eap_peer_get_type(method_str, &retrieved_vendor);
+	if (retrieved_vendor == EAP_VENDOR_IETF &&
+	    retrieved_method == EAP_TYPE_NONE) {
+		const std::string error_msg = "Cannot get EAP method type: " +
+					      std::to_string(method) + ".";
+		return android::hidl::Status::fromServiceSpecificError(
+		    ERROR_GENERIC, error_msg.c_str());
+	}
+
+	if (wpa_ssid->eap.eap_methods) {
+		os_free(wpa_ssid->eap.eap_methods);
+	}
+	// wpa_supplicant can support setting multiple eap methods for each
+	// network. But, this is not really used by Android. So, just adding
+	// support for setting one EAP method for each network. The additional
+	// |eap_method_type| member in the array is used to indicate the end
+	// of list.
+	wpa_ssid->eap.eap_methods =
+	    (eap_method_type *)os_malloc(sizeof(eap_method_type) * 2);
+	if (!wpa_ssid->eap.eap_methods) {
+		return android::hidl::Status::fromServiceSpecificError(
+		    ERROR_GENERIC, "Memory allocation failed.");
+	}
+	wpa_ssid->eap.eap_methods[0].vendor = retrieved_vendor;
+	wpa_ssid->eap.eap_methods[0].method = retrieved_method;
+	wpa_ssid->eap.eap_methods[1].vendor = EAP_VENDOR_IETF;
+	wpa_ssid->eap.eap_methods[1].method = EAP_TYPE_NONE;
+
+	wpa_ssid->leap = 0;
+	wpa_ssid->non_leap = 0;
+	if (retrieved_vendor == EAP_VENDOR_IETF &&
+	    retrieved_method == EAP_TYPE_LEAP) {
+		wpa_ssid->leap++;
+	} else {
+		wpa_ssid->non_leap++;
+	}
+
+	wpa_hexdump(
+	    MSG_MSGDUMP, "eap methods", (u8 *)wpa_ssid->eap.eap_methods,
+	    sizeof(eap_method_type) * 2);
+	resetInternalStateAfterParamsUpdate();
+	return android::hidl::Status::ok();
+}
+
+android::hidl::Status Network::SetEapPhase2Method(int32_t method)
+{
+	struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
+	RETURN_IF_NETWORK_INVALID(wpa_ssid);
+
+	if (method < kEapPhase2MethodMin || method >= kEapMethodMax) {
+		const std::string error_msg = "Invalid EAP Phase2 method: " +
+					      std::to_string(method) + ".";
+		return android::hidl::Status::fromExceptionCode(
+		    android::hidl::Status::EX_ILLEGAL_ARGUMENT,
+		    error_msg.c_str());
+	}
+	return setStringFieldAndResetState(
+	    kEapPhase2MethodStrings[method], &(wpa_ssid->eap.phase2),
+	    "eap phase2");
+}
+
+android::hidl::Status Network::SetEapIdentity(
+    const std::vector<uint8_t> &identity)
+{
+	struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
+	RETURN_IF_NETWORK_INVALID(wpa_ssid);
+
+	return setByteArrayFieldAndResetState(
+	    identity.data(), identity.size(), &(wpa_ssid->eap.identity),
+	    &(wpa_ssid->eap.identity_len), "eap identity");
+}
+
+android::hidl::Status Network::SetEapAnonymousIdentity(
+    const std::vector<uint8_t> &identity)
+{
+	struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
+	RETURN_IF_NETWORK_INVALID(wpa_ssid);
+
+	return setByteArrayFieldAndResetState(
+	    identity.data(), identity.size(),
+	    &(wpa_ssid->eap.anonymous_identity),
+	    &(wpa_ssid->eap.anonymous_identity_len), "eap anonymous_identity");
+}
+
+android::hidl::Status Network::SetEapPassword(
+    const std::vector<uint8_t> &password)
+{
+	struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
+	RETURN_IF_NETWORK_INVALID(wpa_ssid);
+
+	android::hidl::Status status = setByteArrayKeyFieldAndResetState(
+	    password.data(), password.size(), &(wpa_ssid->eap.password),
+	    &(wpa_ssid->eap.password_len), "eap password");
+	if (status.isOk()) {
+		wpa_ssid->eap.flags &= ~EAP_CONFIG_FLAGS_PASSWORD_NTHASH;
+		wpa_ssid->eap.flags &= ~EAP_CONFIG_FLAGS_EXT_PASSWORD;
+	}
+	return status;
+}
+
+android::hidl::Status Network::SetEapCACert(const std::string &path)
+{
+	struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
+	RETURN_IF_NETWORK_INVALID(wpa_ssid);
+
+	return setStringFieldAndResetState(
+	    path.c_str(), &(wpa_ssid->eap.ca_cert), "eap ca_cert");
+}
+
+android::hidl::Status Network::SetEapCAPath(const std::string &path)
+{
+	struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
+	RETURN_IF_NETWORK_INVALID(wpa_ssid);
+
+	return setStringFieldAndResetState(
+	    path.c_str(), &(wpa_ssid->eap.ca_path), "eap ca_path");
+}
+
+android::hidl::Status Network::SetEapClientCert(const std::string &path)
+{
+	struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
+	RETURN_IF_NETWORK_INVALID(wpa_ssid);
+
+	return setStringFieldAndResetState(
+	    path.c_str(), &(wpa_ssid->eap.client_cert), "eap client_cert");
+}
+
+android::hidl::Status Network::SetEapPrivateKey(const std::string &path)
+{
+	struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
+	RETURN_IF_NETWORK_INVALID(wpa_ssid);
+
+	return setStringFieldAndResetState(
+	    path.c_str(), &(wpa_ssid->eap.private_key), "eap private_key");
+}
+
+android::hidl::Status Network::SetEapSubjectMatch(const std::string &match)
+
+{
+	struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
+	RETURN_IF_NETWORK_INVALID(wpa_ssid);
+
+	return setStringFieldAndResetState(
+	    match.c_str(), &(wpa_ssid->eap.subject_match), "eap subject_match");
+}
+
+android::hidl::Status Network::SetEapAltSubjectMatch(const std::string &match)
+{
+	struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
+	RETURN_IF_NETWORK_INVALID(wpa_ssid);
+
+	return setStringFieldAndResetState(
+	    match.c_str(), &(wpa_ssid->eap.altsubject_match),
+	    "eap altsubject_match");
+}
+
+android::hidl::Status Network::SetEapEngine(bool enable)
+{
+	struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
+	RETURN_IF_NETWORK_INVALID(wpa_ssid);
+
+	wpa_ssid->eap.engine = enable ? 1 : 0;
+	return android::hidl::Status::ok();
+}
+
+android::hidl::Status Network::SetEapEngineID(const std::string &id)
+
+{
+	struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
+	RETURN_IF_NETWORK_INVALID(wpa_ssid);
+
+	return setStringFieldAndResetState(
+	    id.c_str(), &(wpa_ssid->eap.engine_id), "eap engine_id");
+	return android::hidl::Status::ok();
+}
+
+android::hidl::Status Network::SetEapDomainSuffixMatch(
+    const std::string &match)
+
+{
+	struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
+	RETURN_IF_NETWORK_INVALID(wpa_ssid);
+
+	return setStringFieldAndResetState(
+	    match.c_str(), &(wpa_ssid->eap.domain_suffix_match),
+	    "eap domain_suffix_match");
+}
+
+android::hidl::Status Network::GetSSID(std::vector<uint8_t> *ssid)
+{
+	struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
+	RETURN_IF_NETWORK_INVALID(wpa_ssid);
+
+	ssid->assign(wpa_ssid->ssid, wpa_ssid->ssid + wpa_ssid->ssid_len);
+	return android::hidl::Status::ok();
+}
+
+android::hidl::Status Network::GetBSSID(std::vector<uint8_t> *bssid)
+{
+	struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
+	RETURN_IF_NETWORK_INVALID(wpa_ssid);
+
+	if (wpa_ssid->bssid_set) {
+		bssid->assign(wpa_ssid->bssid, wpa_ssid->bssid + ETH_ALEN);
+	} else {
+		bssid->clear();
+	}
+	return android::hidl::Status::ok();
+}
+
+android::hidl::Status Network::GetScanSSID(bool *enable)
+{
+	struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
+	RETURN_IF_NETWORK_INVALID(wpa_ssid);
+
+	*enable = (wpa_ssid->scan_ssid == 1);
+	return android::hidl::Status::ok();
+}
+
+android::hidl::Status Network::GetKeyMgmt(int32_t *key_mgmt_mask)
+{
+	struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
+	RETURN_IF_NETWORK_INVALID(wpa_ssid);
+	*key_mgmt_mask = wpa_ssid->key_mgmt;
+	return android::hidl::Status::ok();
+}
+
+android::hidl::Status Network::GetProto(int32_t *proto_mask)
+{
+	struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
+	RETURN_IF_NETWORK_INVALID(wpa_ssid);
+	*proto_mask = wpa_ssid->proto;
+	return android::hidl::Status::ok();
+}
+
+android::hidl::Status Network::GetAuthAlg(int32_t *auth_alg_mask)
+{
+	struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
+	RETURN_IF_NETWORK_INVALID(wpa_ssid);
+	*auth_alg_mask = wpa_ssid->auth_alg;
+	return android::hidl::Status::ok();
+}
+
+android::hidl::Status Network::GetGroupCipher(int32_t *group_cipher_mask)
+{
+	struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
+	RETURN_IF_NETWORK_INVALID(wpa_ssid);
+	*group_cipher_mask = wpa_ssid->group_cipher;
+	return android::hidl::Status::ok();
+}
+
+android::hidl::Status Network::GetPairwiseCipher(
+    int32_t *pairwise_cipher_mask)
+{
+	struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
+	RETURN_IF_NETWORK_INVALID(wpa_ssid);
+	*pairwise_cipher_mask = wpa_ssid->pairwise_cipher;
+	return android::hidl::Status::ok();
+}
+
+android::hidl::Status Network::GetPskPassphrase(std::string *psk)
+{
+	struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
+	RETURN_IF_NETWORK_INVALID(wpa_ssid);
+
+	if (wpa_ssid->passphrase) {
+		*psk = wpa_ssid->passphrase;
+	} else {
+		*psk = std::string();
+	}
+	return android::hidl::Status::ok();
+}
+
+android::hidl::Status Network::GetWepKey(
+    int key_idx, std::vector<uint8_t> *wep_key)
+{
+	struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
+	RETURN_IF_NETWORK_INVALID(wpa_ssid);
+
+	if (key_idx < 0 || key_idx >= WEP_KEYS_MAX_NUM) {
+		const std::string error_msg =
+		    "Invalid Wep Key index: " + std::to_string(key_idx) + ".";
+		return android::hidl::Status::fromExceptionCode(
+		    android::hidl::Status::EX_ILLEGAL_ARGUMENT,
+		    error_msg.c_str());
+	}
+
+	wep_key->assign(
+	    wpa_ssid->wep_key[key_idx],
+	    wpa_ssid->wep_key[key_idx] + wpa_ssid->wep_key_len[key_idx]);
+	return android::hidl::Status::ok();
+}
+
+android::hidl::Status Network::GetWepTxKeyIdx(int32_t *wep_tx_key_idx)
+{
+	struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
+	RETURN_IF_NETWORK_INVALID(wpa_ssid);
+	*wep_tx_key_idx = wpa_ssid->wep_tx_keyidx;
+	return android::hidl::Status::ok();
+}
+
+android::hidl::Status Network::GetRequirePMF(bool *enable)
+{
+	struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
+	RETURN_IF_NETWORK_INVALID(wpa_ssid);
+
+	*enable = (wpa_ssid->ieee80211w == MGMT_FRAME_PROTECTION_REQUIRED);
+	return android::hidl::Status::ok();
+}
+
+android::hidl::Status Network::Enable(bool no_connect)
+{
+	struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
+	RETURN_IF_NETWORK_INVALID(wpa_ssid);
+
+	if (wpa_ssid->disabled == 2) {
+		return android::hidl::Status::fromServiceSpecificError(
+		    ERROR_GENERIC,
+		    "Cannot use Enable with persistent P2P group");
+	}
+
+	struct wpa_supplicant *wpa_s = retrieveIfacePtr();
+	if (no_connect) {
+		wpa_ssid->disabled = 0;
+	} else {
+		wpa_s->scan_min_time.sec = 0;
+		wpa_s->scan_min_time.usec = 0;
+		wpa_supplicant_enable_network(wpa_s, wpa_ssid);
+	}
+	return android::hidl::Status::ok();
+}
+
+android::hidl::Status Network::Disable()
+{
+	struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
+	RETURN_IF_NETWORK_INVALID(wpa_ssid);
+
+	if (wpa_ssid->disabled == 2) {
+		return android::hidl::Status::fromServiceSpecificError(
+		    ERROR_GENERIC,
+		    "Cannot use Disable with persistent P2P group");
+	}
+
+	struct wpa_supplicant *wpa_s = retrieveIfacePtr();
+	wpa_supplicant_disable_network(wpa_s, wpa_ssid);
+	return android::hidl::Status::ok();
+}
+
+android::hidl::Status Network::Select()
+{
+	struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
+	RETURN_IF_NETWORK_INVALID(wpa_ssid);
+
+	if (wpa_ssid->disabled == 2) {
+		return android::hidl::Status::fromServiceSpecificError(
+		    ERROR_GENERIC,
+		    "Cannot use Select with persistent P2P group");
+	}
+
+	struct wpa_supplicant *wpa_s = retrieveIfacePtr();
+	wpa_s->scan_min_time.sec = 0;
+	wpa_s->scan_min_time.usec = 0;
+	wpa_supplicant_select_network(wpa_s, wpa_ssid);
+	return android::hidl::Status::ok();
+}
+
+android::hidl::Status Network::SendNetworkResponse(
+    int type, const std::string &param)
+{
+	struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
+	RETURN_IF_NETWORK_INVALID(wpa_ssid);
+
+	if (type < NETWORK_RSP_UNKNOWN || type > NETWORK_RSP_EXT_CERT_CHECK) {
+		const std::string error_msg =
+		    "Invalid network response type: " + std::to_string(type) +
+		    ".";
+		return android::hidl::Status::fromExceptionCode(
+		    android::hidl::Status::EX_ILLEGAL_ARGUMENT,
+		    error_msg.c_str());
+	}
+
+	enum wpa_ctrl_req_type rtype = (enum wpa_ctrl_req_type)type;
+	struct wpa_supplicant *wpa_s = retrieveIfacePtr();
+	if (wpa_supplicant_ctrl_rsp_handle(
+		wpa_s, wpa_ssid, rtype, param.c_str())) {
+		const std::string error_msg =
+		    "Failed handling network response: " +
+		    std::to_string(type) + ".";
+		return android::hidl::Status::fromServiceSpecificError(
+		    ERROR_GENERIC, error_msg.c_str());
+	}
+	eapol_sm_notify_ctrl_response(wpa_s->eapol);
+	wpa_hexdump_ascii(
+	    MSG_DEBUG, "network response param", (const u8 *)param.c_str(),
+	    param.size());
+	return android::hidl::Status::ok();
+}
+
+/**
+ * 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 *Network::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 *Network::retrieveIfacePtr()
+{
+	return wpa_supplicant_get_iface(
+	    (struct wpa_global *)wpa_global_, ifname_.c_str());
+}
+
+/**
+ * Check if the provided psk passhrase is valid or not.
+ *
+ * Returns 0 if valid, 1 otherwise.
+ */
+int Network::isPskPassphraseValid(const std::string &psk)
+{
+	if (psk.size() < PSK_PASSPHRASE_MIN_LEN ||
+	    psk.size() > PSK_PASSPHRASE_MAX_LEN) {
+		return 1;
+	}
+	if (has_ctrl_char((u8 *)psk.c_str(), psk.size())) {
+		return 1;
+	}
+	return 0;
+}
+
+/**
+ * Reset internal wpa_supplicant state machine state after params update (except
+ * bssid).
+ */
+void Network::resetInternalStateAfterParamsUpdate()
+{
+	struct wpa_supplicant *wpa_s = retrieveIfacePtr();
+	struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
+
+	wpa_sm_pmksa_cache_flush(wpa_s->wpa, wpa_ssid);
+
+	if (wpa_s->current_ssid == wpa_ssid || wpa_s->current_ssid == NULL) {
+		/*
+		 * Invalidate the EAP session cache if anything in the
+		 * current or previously used configuration changes.
+		 */
+		eapol_sm_invalidate_cached_session(wpa_s->eapol);
+	}
+}
+
+/**
+ * Helper function to set value in a string field in |wpa_ssid| structue
+ * instance for this network.
+ * This function frees any existing data in these fields.
+ */
+android::hidl::Status Network::setStringFieldAndResetState(
+    const char *value, uint8_t **to_update_field, const char *hexdump_prefix)
+{
+	return setStringFieldAndResetState(
+	    value, (char **)to_update_field, hexdump_prefix);
+}
+
+/**
+ * Helper function to set value in a string field in |wpa_ssid| structue
+ * instance for this network.
+ * This function frees any existing data in these fields.
+ */
+android::hidl::Status Network::setStringFieldAndResetState(
+    const char *value, char **to_update_field, const char *hexdump_prefix)
+{
+	int value_len = strlen(value);
+	if (*to_update_field) {
+		os_free(*to_update_field);
+	}
+	*to_update_field = dup_binstr(value, value_len);
+	if (!(*to_update_field)) {
+		return android::hidl::Status::fromServiceSpecificError(
+		    ERROR_GENERIC, "Memory allocation failed.");
+	}
+	wpa_hexdump_ascii(
+	    MSG_MSGDUMP, hexdump_prefix, *to_update_field, value_len);
+	resetInternalStateAfterParamsUpdate();
+	return android::hidl::Status::ok();
+}
+
+/**
+ * Helper function to set value in a string key field in |wpa_ssid| structue
+ * instance for this network.
+ * This function frees any existing data in these fields.
+ */
+android::hidl::Status Network::setStringKeyFieldAndResetState(
+    const char *value, char **to_update_field, const char *hexdump_prefix)
+{
+	int value_len = strlen(value);
+	if (*to_update_field) {
+		str_clear_free(*to_update_field);
+	}
+	*to_update_field = dup_binstr(value, value_len);
+	if (!(*to_update_field)) {
+		return android::hidl::Status::fromServiceSpecificError(
+		    ERROR_GENERIC, "Memory allocation failed.");
+	}
+	wpa_hexdump_ascii_key(
+	    MSG_MSGDUMP, hexdump_prefix, *to_update_field, value_len);
+	resetInternalStateAfterParamsUpdate();
+	return android::hidl::Status::ok();
+}
+
+/**
+ * Helper function to set value in a string field with a corresponding length
+ * field in |wpa_ssid| structue instance for this network.
+ * This function frees any existing data in these fields.
+ */
+android::hidl::Status Network::setByteArrayFieldAndResetState(
+    const uint8_t *value, const size_t value_len, uint8_t **to_update_field,
+    size_t *to_update_field_len, const char *hexdump_prefix)
+{
+	if (*to_update_field) {
+		os_free(*to_update_field);
+	}
+	*to_update_field = (uint8_t *)os_malloc(value_len);
+	if (!(*to_update_field)) {
+		return android::hidl::Status::fromServiceSpecificError(
+		    ERROR_GENERIC, "Memory allocation failed.");
+	}
+	os_memcpy(*to_update_field, value, value_len);
+	*to_update_field_len = value_len;
+
+	wpa_hexdump_ascii(
+	    MSG_MSGDUMP, hexdump_prefix, *to_update_field,
+	    *to_update_field_len);
+	resetInternalStateAfterParamsUpdate();
+	return android::hidl::Status::ok();
+}
+
+/**
+ * Helper function to set value in a string key field with a corresponding
+ * length field in |wpa_ssid| structue instance for this network.
+ * This function frees any existing data in these fields.
+ */
+android::hidl::Status Network::setByteArrayKeyFieldAndResetState(
+    const uint8_t *value, const size_t value_len, uint8_t **to_update_field,
+    size_t *to_update_field_len, const char *hexdump_prefix)
+{
+	if (*to_update_field) {
+		bin_clear_free(*to_update_field, *to_update_field_len);
+	}
+	*to_update_field = (uint8_t *)os_malloc(value_len);
+	if (!(*to_update_field)) {
+		return android::hidl::Status::fromServiceSpecificError(
+		    ERROR_GENERIC, "Memory allocation failed.");
+	}
+	os_memcpy(*to_update_field, value, value_len);
+	*to_update_field_len = value_len;
+
+	wpa_hexdump_ascii_key(
+	    MSG_MSGDUMP, hexdump_prefix, *to_update_field,
+	    *to_update_field_len);
+	resetInternalStateAfterParamsUpdate();
+	return android::hidl::Status::ok();
+}
+
+}  // namespace wpa_supplicant_hidl
diff --git a/wpa_supplicant/hidl/network.h b/wpa_supplicant/hidl/network.h
new file mode 100644
index 0000000..331e85a
--- /dev/null
+++ b/wpa_supplicant/hidl/network.h
@@ -0,0 +1,147 @@
+/*
+ * 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_NETWORK_H
+#define WPA_SUPPLICANT_HIDL_NETWORK_H
+
+#include <android-base/macros.h>
+
+#include "fi/w1/wpa_supplicant/BnNetwork.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 wpa_supplicant_hidl {
+
+/**
+ * Implementation of Network hidl object. Each unique hidl
+ * object is used for control operations on a specific network
+ * controlled by wpa_supplicant.
+ */
+class Network : public fi::w1::wpa_supplicant::BnNetwork
+{
+public:
+	Network(
+	    struct wpa_global *wpa_global, const char ifname[], int network_id);
+	~Network() override = default;
+
+	// Hidl methods exposed in aidl.
+	android::hidl::Status GetId(int *network_id_out) override;
+	android::hidl::Status GetInterfaceName(
+	    std::string *ifname_out) override;
+	android::hidl::Status RegisterCallback(
+	    const android::sp<fi::w1::wpa_supplicant::INetworkCallback>
+		&callback) override;
+	android::hidl::Status SetSSID(
+	    const std::vector<uint8_t> &ssid) override;
+	android::hidl::Status SetBSSID(
+	    const std::vector<uint8_t> &bssid) override;
+	android::hidl::Status SetScanSSID(bool enable) override;
+	android::hidl::Status SetKeyMgmt(int32_t key_mgmt_mask) override;
+	android::hidl::Status SetProto(int32_t proto_mask) override;
+	android::hidl::Status SetAuthAlg(int32_t auth_alg_mask) override;
+	android::hidl::Status SetGroupCipher(
+	    int32_t group_cipher_mask) override;
+	android::hidl::Status SetPairwiseCipher(
+	    int32_t pairwise_cipher_mask) override;
+	android::hidl::Status SetPskPassphrase(
+	    const std::string &psk) override;
+	android::hidl::Status SetWepKey(
+	    int key_idx, const std::vector<uint8_t> &wep_key) override;
+	android::hidl::Status SetWepTxKeyIdx(int32_t wep_tx_key_idx) override;
+	android::hidl::Status SetRequirePMF(bool enable) override;
+	android::hidl::Status SetEapMethod(int32_t method) override;
+	android::hidl::Status SetEapPhase2Method(int32_t method) override;
+	android::hidl::Status SetEapIdentity(
+	    const std::vector<uint8_t> &identity) override;
+	android::hidl::Status SetEapAnonymousIdentity(
+	    const std::vector<uint8_t> &identity) override;
+	android::hidl::Status SetEapPassword(
+	    const std::vector<uint8_t> &password) override;
+	android::hidl::Status SetEapCACert(const std::string &path) override;
+	android::hidl::Status SetEapCAPath(const std::string &path) override;
+	android::hidl::Status SetEapClientCert(
+	    const std::string &path) override;
+	android::hidl::Status SetEapPrivateKey(
+	    const std::string &path) override;
+	android::hidl::Status SetEapSubjectMatch(
+	    const std::string &match) override;
+	android::hidl::Status SetEapAltSubjectMatch(
+	    const std::string &match) override;
+	android::hidl::Status SetEapEngine(bool enable) override;
+	android::hidl::Status SetEapEngineID(const std::string &id) override;
+	android::hidl::Status SetEapDomainSuffixMatch(
+	    const std::string &match) override;
+	android::hidl::Status GetSSID(std::vector<uint8_t> *ssid) override;
+	android::hidl::Status GetBSSID(std::vector<uint8_t> *bssid) override;
+	android::hidl::Status GetScanSSID(bool *enable) override;
+	android::hidl::Status GetKeyMgmt(int32_t *key_mgmt_mask) override;
+	android::hidl::Status GetProto(int32_t *proto_mask) override;
+	android::hidl::Status GetAuthAlg(int32_t *auth_alg_mask) override;
+	android::hidl::Status GetGroupCipher(
+	    int32_t *group_cipher_mask) override;
+	android::hidl::Status GetPairwiseCipher(
+	    int32_t *pairwise_cipher_mask) override;
+	android::hidl::Status GetPskPassphrase(std::string *psk) override;
+	android::hidl::Status GetWepKey(
+	    int key_idx, std::vector<uint8_t> *wep_key) override;
+	android::hidl::Status GetWepTxKeyIdx(
+	    int32_t *wep_tx_key_idx) override;
+	android::hidl::Status GetRequirePMF(bool *enable) override;
+	android::hidl::Status Enable(bool no_connect) override;
+	android::hidl::Status Disable() override;
+	android::hidl::Status Select() override;
+	android::hidl::Status SendNetworkResponse(
+	    int type, const std::string &param) override;
+
+private:
+	struct wpa_ssid *retrieveNetworkPtr();
+	struct wpa_supplicant *retrieveIfacePtr();
+	int isPskPassphraseValid(const std::string &psk);
+	void resetInternalStateAfterParamsUpdate();
+	android::hidl::Status setStringFieldAndResetState(
+	    const char *value, uint8_t **to_update_field,
+	    const char *hexdump_prefix);
+	android::hidl::Status setStringFieldAndResetState(
+	    const char *value, char **to_update_field,
+	    const char *hexdump_prefix);
+	android::hidl::Status setStringKeyFieldAndResetState(
+	    const char *value, char **to_update_field,
+	    const char *hexdump_prefix);
+	android::hidl::Status setByteArrayFieldAndResetState(
+	    const uint8_t *value, const size_t value_len,
+	    uint8_t **to_update_field, size_t *to_update_field_len,
+	    const char *hexdump_prefix);
+	android::hidl::Status setByteArrayKeyFieldAndResetState(
+	    const uint8_t *value, const size_t value_len,
+	    uint8_t **to_update_field, size_t *to_update_field_len,
+	    const char *hexdump_prefix);
+
+	// 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(Network);
+};
+
+}  // namespace wpa_supplicant_hidl
+
+#endif  // WPA_SUPPLICANT_HIDL_NETWORK_H
diff --git a/wpa_supplicant/hidl/supplicant.cpp b/wpa_supplicant/hidl/supplicant.cpp
new file mode 100644
index 0000000..3ff514e
--- /dev/null
+++ b/wpa_supplicant/hidl/supplicant.cpp
@@ -0,0 +1,258 @@
+/*
+ * 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 "supplicant.h"
+#include "hidl_manager.h"
+#include "../src/utils/wpa_debug.h"
+
+namespace wpa_supplicant_hidl {
+
+Supplicant::Supplicant(struct wpa_global *global) : wpa_global_(global) {}
+android::hidl::Status Supplicant::CreateInterface(
+    const fi::w1::wpa_supplicant::ParcelableIfaceParams &params,
+    android::sp<fi::w1::wpa_supplicant::IIface> *iface_object_out)
+{
+	/* Check if required Ifname argument is missing */
+	if (params.ifname_.isEmpty()) {
+		return android::hidl::Status::fromExceptionCode(
+		    android::hidl::Status::EX_ILLEGAL_ARGUMENT,
+		    "Ifname missing in params.");
+	}
+	/*
+	 * Try to get the wpa_supplicant record for this iface, return
+	 * an error if we already control it.
+	 */
+	if (wpa_supplicant_get_iface(wpa_global_, params.ifname_.string()) !=
+	    NULL) {
+		return android::hidl::Status::fromServiceSpecificError(
+		    ERROR_IFACE_EXISTS,
+		    "wpa_supplicant already controls this interface.");
+	}
+
+	android::hidl::Status status;
+	struct wpa_supplicant *wpa_s = NULL;
+	struct wpa_interface iface;
+
+	os_memset(&iface, 0, sizeof(iface));
+	iface.driver = os_strdup(params.driver_.string());
+	iface.ifname = os_strdup(params.ifname_.string());
+	iface.confname = os_strdup(params.config_file_.string());
+	iface.bridge_ifname = os_strdup(params.bridge_ifname_.string());
+	/* Otherwise, have wpa_supplicant attach to it. */
+	wpa_s = wpa_supplicant_add_iface(wpa_global_, &iface, NULL);
+	/* The supplicant core creates a corresponding hidl object via
+	 * HidlManager when |wpa_supplicant_add_iface| is called. */
+	if (!wpa_s) {
+		status = android::hidl::Status::fromServiceSpecificError(
+		    ERROR_GENERIC,
+		    "wpa_supplicant couldn't grab this interface.");
+	} else {
+		HidlManager *hidl_manager = HidlManager::getInstance();
+
+		if (!hidl_manager ||
+		    hidl_manager->getIfaceHidlObjectByIfname(
+			wpa_s->ifname, iface_object_out)) {
+			status =
+			    android::hidl::Status::fromServiceSpecificError(
+				ERROR_GENERIC,
+				"wpa_supplicant encountered a hidl error.");
+		} else {
+			status = android::hidl::Status::ok();
+		}
+	}
+	os_free((void *)iface.driver);
+	os_free((void *)iface.ifname);
+	os_free((void *)iface.confname);
+	os_free((void *)iface.bridge_ifname);
+	return status;
+}
+
+android::hidl::Status Supplicant::RemoveInterface(const std::string &ifname)
+{
+	struct wpa_supplicant *wpa_s;
+
+	wpa_s = wpa_supplicant_get_iface(wpa_global_, ifname.c_str());
+	if (!wpa_s) {
+		return android::hidl::Status::fromServiceSpecificError(
+		    ERROR_IFACE_UNKNOWN,
+		    "wpa_supplicant does not control this interface.");
+	}
+	if (wpa_supplicant_remove_iface(wpa_global_, wpa_s, 0)) {
+		return android::hidl::Status::fromServiceSpecificError(
+		    ERROR_GENERIC,
+		    "wpa_supplicant couldn't remove this interface.");
+	}
+	return android::hidl::Status::ok();
+}
+
+android::hidl::Status Supplicant::GetInterface(
+    const std::string &ifname,
+    android::sp<fi::w1::wpa_supplicant::IIface> *iface_object_out)
+{
+	struct wpa_supplicant *wpa_s;
+
+	wpa_s = wpa_supplicant_get_iface(wpa_global_, ifname.c_str());
+	if (!wpa_s) {
+		return android::hidl::Status::fromServiceSpecificError(
+		    ERROR_IFACE_UNKNOWN,
+		    "wpa_supplicant does not control this interface.");
+	}
+
+	HidlManager *hidl_manager = HidlManager::getInstance();
+	if (!hidl_manager ||
+	    hidl_manager->getIfaceHidlObjectByIfname(
+		wpa_s->ifname, iface_object_out)) {
+		return android::hidl::Status::fromServiceSpecificError(
+		    ERROR_GENERIC,
+		    "wpa_supplicant encountered a hidl error.");
+	}
+
+	return android::hidl::Status::ok();
+}
+
+android::hidl::Status Supplicant::SetDebugParams(
+    int level, bool show_timestamp, bool show_keys)
+{
+	int internal_level;
+	if (convertDebugLevelToInternalLevel(level, &internal_level)) {
+		const std::string error_msg =
+		    "invalid debug level: " + std::to_string(level);
+		return android::hidl::Status::fromExceptionCode(
+		    android::hidl::Status::EX_ILLEGAL_ARGUMENT,
+		    error_msg.c_str());
+	}
+	if (wpa_supplicant_set_debug_params(
+<<<<<<< 390ba2881ef621db480848b7e50b93d61542206a:wpa_supplicant/binder/supplicant.cpp
+		wpa_global_, internal_level, show_timestamp, show_keys)) {
+		return android::binder::Status::fromServiceSpecificError(
+=======
+		wpa_global_, level, show_timestamp, show_keys)) {
+		return android::hidl::Status::fromServiceSpecificError(
+>>>>>>> wpa_supplicant: HIDL implementation (1/2):wpa_supplicant/hidl/supplicant.cpp
+		    ERROR_GENERIC,
+		    "wpa_supplicant could not set debug params.");
+	}
+	return android::hidl::Status::ok();
+}
+
+android::hidl::Status Supplicant::GetDebugLevel(int *level_out)
+{
+<<<<<<< 390ba2881ef621db480848b7e50b93d61542206a:wpa_supplicant/binder/supplicant.cpp
+	if (convertDebugLevelToExternalLevel(wpa_debug_level, level_out)) {
+		const std::string error_msg =
+		    "invalid debug level: " + std::to_string(wpa_debug_level);
+		return android::binder::Status::fromExceptionCode(
+		    android::binder::Status::EX_ILLEGAL_ARGUMENT,
+		    error_msg.c_str());
+	}
+	return android::binder::Status::ok();
+=======
+	*level_out = wpa_debug_level;
+	return android::hidl::Status::ok();
+>>>>>>> wpa_supplicant: HIDL implementation (1/2):wpa_supplicant/hidl/supplicant.cpp
+}
+
+android::hidl::Status Supplicant::GetDebugShowTimestamp(
+    bool *show_timestamp_out)
+{
+	*show_timestamp_out = wpa_debug_timestamp ? true : false;
+	return android::hidl::Status::ok();
+}
+
+android::hidl::Status Supplicant::GetDebugShowKeys(bool *show_keys_out)
+{
+	*show_keys_out = wpa_debug_show_keys ? true : false;
+	return android::hidl::Status::ok();
+}
+
+android::hidl::Status Supplicant::RegisterCallback(
+    const android::sp<fi::w1::wpa_supplicant::ISupplicantCallback> &callback)
+{
+	HidlManager *hidl_manager = HidlManager::getInstance();
+	if (!hidl_manager ||
+	    hidl_manager->addSupplicantCallbackHidlObject(callback)) {
+		return android::hidl::Status::fromServiceSpecificError(
+		    ERROR_GENERIC,
+		    "wpa_supplicant encountered a hidl error.");
+	}
+	return android::hidl::Status::ok();
+}
+<<<<<<< 390ba2881ef621db480848b7e50b93d61542206a:wpa_supplicant/binder/supplicant.cpp
+
+/**
+ * Helper function to convert the debug level parameter from the binder
+ * interface values to internal values.
+ */
+int Supplicant::convertDebugLevelToInternalLevel(
+    int external_level, int *internal_level)
+{
+	switch (external_level) {
+	case DEBUG_LEVEL_EXCESSIVE:
+		*internal_level = MSG_EXCESSIVE;
+		return 0;
+	case DEBUG_LEVEL_MSGDUMP:
+		*internal_level = MSG_MSGDUMP;
+		return 0;
+	case DEBUG_LEVEL_DEBUG:
+		*internal_level = MSG_DEBUG;
+		return 0;
+	case DEBUG_LEVEL_INFO:
+		*internal_level = MSG_INFO;
+		return 0;
+	case DEBUG_LEVEL_WARNING:
+		*internal_level = MSG_WARNING;
+		return 0;
+	case DEBUG_LEVEL_ERROR:
+		*internal_level = MSG_ERROR;
+		return 0;
+	default:
+		wpa_printf(
+		    MSG_ERROR, "Invalid external log level: %d",
+		    external_level);
+		return 1;
+	}
+}
+
+/**
+ * Helper function to convert the debug level parameter from the internal values
+ * to binder interface values.
+ */
+int Supplicant::convertDebugLevelToExternalLevel(
+    int internal_level, int *external_level)
+{
+	switch (internal_level) {
+	case MSG_EXCESSIVE:
+		*external_level = DEBUG_LEVEL_EXCESSIVE;
+		return 0;
+	case MSG_MSGDUMP:
+		*external_level = DEBUG_LEVEL_MSGDUMP;
+		return 0;
+	case MSG_DEBUG:
+		*external_level = DEBUG_LEVEL_DEBUG;
+		return 0;
+	case MSG_INFO:
+		*external_level = DEBUG_LEVEL_INFO;
+		return 0;
+	case MSG_WARNING:
+		*external_level = DEBUG_LEVEL_WARNING;
+		return 0;
+	case MSG_ERROR:
+		*external_level = DEBUG_LEVEL_ERROR;
+		return 0;
+	default:
+		wpa_printf(
+		    MSG_ERROR, "Invalid internal log level: %d",
+		    internal_level);
+		return 1;
+	}
+}
+} /* namespace wpa_supplicant_binder */
+=======
+} /* namespace wpa_supplicant_hidl */
+>>>>>>> wpa_supplicant: HIDL implementation (1/2):wpa_supplicant/hidl/supplicant.cpp
diff --git a/wpa_supplicant/hidl/supplicant.h b/wpa_supplicant/hidl/supplicant.h
new file mode 100644
index 0000000..9805289
--- /dev/null
+++ b/wpa_supplicant/hidl/supplicant.h
@@ -0,0 +1,76 @@
+/*
+ * 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_SUPPLICANT_H
+#define WPA_SUPPLICANT_HIDL_SUPPLICANT_H
+
+#include <android-base/macros.h>
+
+#include "fi/w1/wpa_supplicant/BnSupplicant.h"
+#include "fi/w1/wpa_supplicant/IIface.h"
+#include "fi/w1/wpa_supplicant/ISupplicantCallback.h"
+
+extern "C" {
+#include "utils/common.h"
+#include "utils/includes.h"
+#include "../wpa_supplicant_i.h"
+}
+
+namespace wpa_supplicant_hidl {
+
+/**
+ * Implementation of the supplicant hidl object. This hidl
+ * object is used core for global control operations on
+ * wpa_supplicant.
+ */
+class Supplicant : public fi::w1::wpa_supplicant::BnSupplicant
+{
+public:
+	Supplicant(struct wpa_global *global);
+	~Supplicant() override = default;
+
+	// Hidl methods exposed in aidl.
+	android::hidl::Status CreateInterface(
+	    const fi::w1::wpa_supplicant::ParcelableIfaceParams &params,
+	    android::sp<fi::w1::wpa_supplicant::IIface> *iface_object_out)
+	    override;
+	android::hidl::Status RemoveInterface(
+	    const std::string &ifname) override;
+	android::hidl::Status GetInterface(
+	    const std::string &ifname,
+	    android::sp<fi::w1::wpa_supplicant::IIface> *iface_object_out)
+	    override;
+	android::hidl::Status SetDebugParams(
+	    int level, bool show_timestamp, bool show_keys) override;
+	android::hidl::Status GetDebugLevel(int *level_out) override;
+	android::hidl::Status GetDebugShowTimestamp(
+	    bool *show_timestamp_out) override;
+	android::hidl::Status GetDebugShowKeys(bool *show_keys_out) override;
+	android::hidl::Status RegisterCallback(
+	    const android::sp<fi::w1::wpa_supplicant::ISupplicantCallback>
+		&callback) override;
+
+private:
+	int convertDebugLevelToInternalLevel(
+	    int external_level, int *internal_level);
+	int convertDebugLevelToExternalLevel(
+	    int internal_level, int *external_level);
+
+	/* Raw pointer to the global structure maintained by the core. */
+	struct wpa_global *wpa_global_;
+	/* All the callback objects registered by the clients. */
+	std::vector<android::sp<fi::w1::wpa_supplicant::ISupplicantCallback>>
+	    callbacks_;
+
+	DISALLOW_COPY_AND_ASSIGN(Supplicant);
+};
+
+} /* namespace wpa_supplicant_hidl */
+
+#endif /* WPA_SUPPLICANT_HIDL_SUPPLICANT_H */