Cumulative patch from commit f89c32e63f71e66d7b55e284016762b603ae02db

f89c32e Android: Fix max number of sched scan SSIDs based on driver capability
f1a5a34 binder: Implement interface add/remove methods
7b4bbb9 binder: Add binder skeletal code for Android
5914ebf Remove struct ieee80211_mgmt::u.probe_req
094e949 atheros: Do not use struct ieee80211_mgmt::u.probe_req
c01120a wpa_supplicant: Do not use struct ieee80211_mgmt::u.probe_req
e1b9962 AP: Do not use struct ieee80211_mgmt::u.probe_req
5cd317d Do not clear PMKSA entry or EAP session cache if config does not change
f933216 Revert "Assign QCA vendor command and attribute for Tx/Rx aggregation"
bde9a4e Comment out UDP/UNIX socket code from common ctrl_iface based on build
a6fbff2 Fix CONFIG_CTRL_IFACE=udp6/udp6-remote builds
0741c48 SAE: Check SHA256-PRF operation result
ea86a34 SAE: Remove dead code in FFC pwd-value derivation
87faf1f nl80211: Fix libnl-tiny build with CONFIG_LIBNL20=y
31afdd2 Use TIOCOUTQ instead of SIOCOUTQ to avoid need for linux/sockios.h
6d07e76 wlantest: Use local ETH_P_IP define instead of linux/if_ether.h
795abc8 Drop USE_KERNEL_HEADERS define
9b7cd57 Use a separate header file for Linux bridge interface definitions
c815fab Use own header file for defining Linux VLAN kernel interface
81606ab vlan: Fix musl libc conflict with Linux kernel headers
f347429 P2P: Fix persistent group for 60 GHz networks
e868599 vlan: Move if_nametoindex() use out of vlan_init.c
7c03c08 vlan: Move ifconfig helpers to a separate file
59d6390 vlan: Move CONFIG_FULL_DYNAMIC_VLAN functionality into a separate file
0fe28dd vlan: Remove unnecessary header includes from netlink implementation
84d6755 vlan: Clean up netlink vs. ioctl API implementation
cb38bc8 vlan: Fix musl build error
954e10e Make it a bit easier to roam from 2.4 GHz to 5 GHz within ESS
585141b Fix a typo in a comment
1126c07 nl80211: Ignore deauth/disassoc event during Connect reassociation
6a5ee81 Include previous BSSID in connection request to indicate reassociation
00c3c4a nl80211: Add NL80211_ATTR_PREV_BSSID with Connect command
cbc3d6f WNM: Verify BSS TM target match against the current network profile
8854f90 mesh: Simplify wpa_auth_pmksa_set_to_sm()
32d4fe9 privsep: Fix a compiler warning on unsigned/signed comparison
2e997ee Add interface matching support with -M, guarded by CONFIG_MATCH_IFACE
45e3fc7 Find correct driver for interface additions/removals
9037702 wpa_supplicant: Fix CONFIG_IBSS_RSN=y build without CONFIG_AP=y
5ae65de wpa_supplicant: Fix p2p_group_add when UDP-based ctrl_iface is used
24bce46 FST: Fix a compiler warning
e567c58 Fix nfc_pw_token build with CONFIG_FST=y
d774c46 mesh: Use appropriate BLOCKED state duration
9f2cf23 mesh: Add support for PMKSA caching
4c522c7 PMKSA: Flush AP/mesh PMKSA cache by PMKSA_FLUSH command
b8daac1 PMKSA: Show AP/mesh PMKSA list in PMKSA command
2604edb mesh: Add MESH_PEER_ADD command
e174ef3 mesh: Add MESH_PEER_REMOVE command
f7648c8 P2P: Advertise IP Address Allocation only if it is enabled on GO
7f46ad9 BSD: Only down the interface once we are sure we can work with it
192964d Handle OSEN IE in Assoc Request info if req_ies exists
29eddc3 nl80211: Fix error path in if_indices_reason reallocation
ee298f1 nl80211: Do not add NL80211_ATTR_SMPS_MODE attribute if HT is disabled
4ca16b5 Assign QCA vendor command and attribute for Tx/Rx aggregation
64ce590 libxml2: Check for xmlDocDumpFormatMemory() error case
8b827c3 BoringSSL: Keep static analyzers happier with X509_get0_pubkey_bitstr()
42a9553 hs20-osu-client: Fix pol_upd command line parsing
ec1eae8 hs20-osu-client: Remove dead code from sub_rem command line parsing
c3dc68e Do not invalidate EAP session cache on all network block parameter changes
9231c24 wlantest: Fix bip_protect() memory allocation
c6c29be Interworking: Add credential realm to EAP-TLS identity

Change-Id: I870f325171d00fed9c4fcd82a695fe5e2efee792
Signed-off-by: Dmitry Shmidt <dimitrysh@google.com>
diff --git a/wpa_supplicant/binder/binder.cpp b/wpa_supplicant/binder/binder.cpp
new file mode 100644
index 0000000..28f7a2b
--- /dev/null
+++ b/wpa_supplicant/binder/binder.cpp
@@ -0,0 +1,108 @@
+/*
+ * binder 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 <binder/IPCThreadState.h>
+#include <binder/ProcessState.h>
+#include <binder/IServiceManager.h>
+
+#include "binder_manager.h"
+
+extern "C" {
+#include "utils/includes.h"
+#include "utils/common.h"
+#include "utils/eloop.h"
+#include "binder.h"
+#include "binder_i.h"
+}
+
+void wpas_binder_sock_handler(int sock, void *eloop_ctx, void *sock_ctx)
+{
+	struct wpa_global *global = (wpa_global *) eloop_ctx;
+	struct wpas_binder_priv *priv = (wpas_binder_priv *) sock_ctx;
+
+	wpa_printf(MSG_DEBUG, "Processing binder events on FD %d",
+		   priv->binder_fd);
+	android::IPCThreadState::self()->handlePolledCommands();
+}
+
+
+struct wpas_binder_priv * wpas_binder_init(struct wpa_global *global)
+{
+	struct wpas_binder_priv *priv;
+	wpa_supplicant_binder::BinderManager *binder_manager;
+
+	priv = (wpas_binder_priv *) os_zalloc(sizeof(*priv));
+	if (!priv)
+		return NULL;
+	priv->global = global;
+
+	android::ProcessState::self()->setThreadPoolMaxThreadCount(0);
+	android::IPCThreadState::self()->disableBackgroundScheduling(true);
+	android::IPCThreadState::self()->setupPolling(&priv->binder_fd);
+	wpa_printf(MSG_INFO, "Process binder events on FD %d", priv->binder_fd);
+	if (priv->binder_fd < 0)
+		goto err;
+	/* Look for read events from the binder socket in the eloop. */
+	if (eloop_register_read_sock(priv->binder_fd, wpas_binder_sock_handler,
+				     global, priv) < 0)
+		goto err;
+
+	binder_manager = wpa_supplicant_binder::BinderManager::getInstance();
+	if (!binder_manager)
+		goto err;
+	binder_manager->registerBinderService(global);
+	/* We may not need to store this binder manager reference in the
+	 * global data strucure because we've made it a singleton class. */
+	priv->binder_manager = (void *) binder_manager;
+
+	return priv;
+
+err:
+	wpas_binder_deinit(priv);
+	return NULL;
+}
+
+
+void wpas_binder_deinit(struct wpas_binder_priv *priv)
+{
+	if (!priv)
+		return;
+
+	wpa_supplicant_binder::BinderManager::destroyInstance();
+	eloop_unregister_read_sock(priv->binder_fd);
+	android::IPCThreadState::shutdown();
+}
+
+
+int wpas_binder_register_interface(struct wpa_supplicant *wpa_s)
+{
+	if (!wpa_s->global->binder)
+		return 1;
+
+	wpa_supplicant_binder::BinderManager *binder_manager =
+		wpa_supplicant_binder::BinderManager::getInstance();
+	if (!binder_manager)
+		return 1;
+
+	return binder_manager->registerInterface(wpa_s);
+}
+
+
+int wpas_binder_unregister_interface(struct wpa_supplicant *wpa_s)
+{
+	if (!wpa_s->global->binder)
+		return 1;
+
+	wpa_supplicant_binder::BinderManager *binder_manager =
+		wpa_supplicant_binder::BinderManager::getInstance();
+	if (!binder_manager)
+		return 1;
+
+	return binder_manager->unregisterInterface(wpa_s);
+}
diff --git a/wpa_supplicant/binder/binder.h b/wpa_supplicant/binder/binder.h
new file mode 100644
index 0000000..a165074
--- /dev/null
+++ b/wpa_supplicant/binder/binder.h
@@ -0,0 +1,46 @@
+/*
+ * binder 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 BINDER_H
+#define BINDER_H
+
+#ifdef _cplusplus
+extern "C" {
+#endif /* _cplusplus */
+
+/**
+ * This is the binder RPC interface entry point to the wpa_supplicant core.
+ * This initializes the binder driver & BinderManager instance and then forwards
+ * all the notifcations from the supplicant core to the BinderManager.
+ */
+struct wpas_binder_priv;
+struct wpa_global;
+
+struct wpas_binder_priv * wpas_binder_init(struct wpa_global *global);
+void wpas_binder_deinit(struct wpas_binder_priv *priv);
+
+#ifdef CONFIG_CTRL_IFACE_BINDER
+int wpas_binder_register_interface(struct wpa_supplicant *wpa_s);
+int wpas_binder_unregister_interface(struct wpa_supplicant *wpa_s);
+#else /* CONFIG_CTRL_IFACE_BINDER */
+static inline int wpas_binder_register_interface(struct wpa_supplicant *wpa_s)
+{
+	return 0;
+}
+static inline int wpas_binder_unregister_interface(struct wpa_supplicant *wpa_s)
+{
+	return 0;
+}
+#endif /* CONFIG_CTRL_IFACE_BINDER */
+
+#ifdef _cplusplus
+}
+#endif /* _cplusplus */
+
+#endif /* BINDER_H */
diff --git a/wpa_supplicant/binder/binder_i.h b/wpa_supplicant/binder/binder_i.h
new file mode 100644
index 0000000..e8087b6
--- /dev/null
+++ b/wpa_supplicant/binder/binder_i.h
@@ -0,0 +1,27 @@
+/*
+ * binder 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 BINDER_I_H
+#define BINDER_I_H
+
+#ifdef _cplusplus
+extern "C" {
+#endif // _cplusplus
+
+struct wpas_binder_priv {
+	int binder_fd;
+	struct wpa_global *global;
+	void *binder_manager;
+};
+
+#ifdef _cplusplus
+}
+#endif /* _cplusplus */
+
+#endif /* BINDER_I_H */
diff --git a/wpa_supplicant/binder/binder_manager.cpp b/wpa_supplicant/binder/binder_manager.cpp
new file mode 100644
index 0000000..728f4b7
--- /dev/null
+++ b/wpa_supplicant/binder/binder_manager.cpp
@@ -0,0 +1,107 @@
+/*
+ * binder 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 <binder/IServiceManager.h>
+
+#include "binder_manager.h"
+
+extern "C" {
+#include "utils/includes.h"
+#include "utils/common.h"
+}
+
+namespace wpa_supplicant_binder {
+
+const char BinderManager::kBinderServiceName[] = "fi.w1.wpa_supplicant";
+BinderManager *BinderManager::instance_ = NULL;
+
+
+BinderManager * BinderManager::getInstance()
+{
+	if (!instance_)
+		instance_ = new BinderManager();
+	return instance_;
+}
+
+
+void BinderManager::destroyInstance()
+{
+	if (instance_)
+		delete instance_;
+	instance_ = NULL;
+}
+
+
+int BinderManager::registerBinderService(struct wpa_global *global)
+{
+	/* Create the main binder service object and register with
+	 * system service manager. */
+	supplicant_object_ = new Supplicant(global);
+	android::String16 service_name(kBinderServiceName);
+	android::defaultServiceManager()->addService(
+		service_name,
+		android::IInterface::asBinder(supplicant_object_));
+	return 0;
+}
+
+
+int BinderManager::registerInterface(struct wpa_supplicant *wpa_s)
+{
+	if (!wpa_s)
+		return 1;
+
+	/* Using the corresponding wpa_supplicant pointer as key to our
+	 * object map. */
+	const void *iface_key = wpa_s;
+
+	/* Return failure if we already have an object for that iface_key. */
+	if (iface_object_map_.find(iface_key) != iface_object_map_.end())
+		return 1;
+
+	iface_object_map_[iface_key] = new Iface(wpa_s);
+	if (!iface_object_map_[iface_key].get())
+		return 1;
+
+	wpa_s->binder_object_key = iface_key;
+
+	return 0;
+}
+
+
+int BinderManager::unregisterInterface(struct wpa_supplicant *wpa_s)
+{
+	if (!wpa_s || !wpa_s->binder_object_key)
+		return 1;
+
+	const void *iface_key = wpa_s;
+	if (iface_object_map_.find(iface_key) == iface_object_map_.end())
+		return 1;
+
+	/* Delete the corresponding iface object from our map. */
+	iface_object_map_.erase(iface_key);
+	wpa_s->binder_object_key = NULL;
+	return 0;
+}
+
+
+int BinderManager::getIfaceBinderObjectByKey(
+	const void *iface_object_key,
+	android::sp<fi::w1::wpa_supplicant::IIface> *iface_object)
+{
+	if (!iface_object_key || !iface_object)
+		return 1;
+
+	if (iface_object_map_.find(iface_object_key) == iface_object_map_.end())
+		return 1;
+
+	*iface_object = iface_object_map_[iface_object_key];
+	return 0;
+}
+
+} /* namespace wpa_supplicant_binder */
diff --git a/wpa_supplicant/binder/binder_manager.h b/wpa_supplicant/binder/binder_manager.h
new file mode 100644
index 0000000..687e740
--- /dev/null
+++ b/wpa_supplicant/binder/binder_manager.h
@@ -0,0 +1,59 @@
+/*
+ * binder 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 BINDER_MANAGER_H
+#define BINDER_MANAGER_H
+
+#include <map>
+#include <string>
+
+#include "supplicant.h"
+#include "iface.h"
+
+struct wpa_global;
+struct wpa_supplicant;
+
+namespace wpa_supplicant_binder {
+
+/**
+ * BinderManager is responsible for managing the lifetime of all
+ * binder 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 binder objects.
+ */
+class BinderManager {
+public:
+	static const char kBinderServiceName[];
+
+	static BinderManager * getInstance();
+	static void destroyInstance();
+	int registerBinderService(struct wpa_global *global);
+	int registerInterface(struct wpa_supplicant *wpa_s);
+	int unregisterInterface(struct wpa_supplicant *wpa_s);
+	int getIfaceBinderObjectByKey(
+		const void *iface_object_key,
+		android::sp<fi::w1::wpa_supplicant::IIface> *iface_object);
+
+private:
+	BinderManager() = default;
+	~BinderManager() = default;
+
+	/* Singleton instance of this class. */
+	static BinderManager *instance_;
+	/* The main binder service object. */
+	android::sp<Supplicant> supplicant_object_;
+	/* Map of all the interface specific binder objects controlled by
+	 * wpa_supplicant. This map is keyed in by the corresponding
+	 * wpa_supplicant structure pointer. */
+	std::map<const void *, android::sp<Iface>> iface_object_map_;
+};
+
+} /* namespace wpa_supplicant_binder */
+
+#endif /* BINDER_MANAGER_H */
diff --git a/wpa_supplicant/binder/fi/w1/wpa_supplicant/IIface.aidl b/wpa_supplicant/binder/fi/w1/wpa_supplicant/IIface.aidl
new file mode 100644
index 0000000..ea11d42
--- /dev/null
+++ b/wpa_supplicant/binder/fi/w1/wpa_supplicant/IIface.aidl
@@ -0,0 +1,16 @@
+/*
+ * binder 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.
+ */
+
+package fi.w1.wpa_supplicant;
+
+/**
+ * Interface exposed by wpa_supplicant for each network interface it controls.
+ */
+interface IIface {
+}
diff --git a/wpa_supplicant/binder/fi/w1/wpa_supplicant/ISupplicant.aidl b/wpa_supplicant/binder/fi/w1/wpa_supplicant/ISupplicant.aidl
new file mode 100644
index 0000000..1cbee20
--- /dev/null
+++ b/wpa_supplicant/binder/fi/w1/wpa_supplicant/ISupplicant.aidl
@@ -0,0 +1,59 @@
+/*
+ * WPA Supplicant - binder 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.
+ */
+
+package fi.w1.wpa_supplicant;
+
+import android.os.PersistableBundle;
+import fi.w1.wpa_supplicant.IIface;
+
+/**
+ * Interface exposed by the wpa_supplicant binder service registered
+ * with the service manager with name: fi.w1.wpa_supplicant.
+ */
+interface ISupplicant {
+	/* Error values returned by the service to RPC method calls. */
+	const int ERROR_INVALID_ARGS = 1;
+	const int ERROR_UNKNOWN = 2;
+	const int ERROR_IFACE_EXISTS = 3;
+	const int ERROR_IFACE_UNKNOWN = 4;
+
+	/**
+	 * Registers a wireless interface in wpa_supplicant.
+	 *
+	 * @param args A dictionary with arguments used to add the interface to
+	 *             wpa_supplicant.
+	 * The dictionary may contain the following entries:
+	 *   Ifname(String) Name of the network interface to control, e.g.,
+	 *   wlan0.
+	 *   BridgeIfname(String) Name of the bridge interface to control, e.g.,
+	 *   br0.
+	 *   Driver(String) Driver name which the interface uses, e.g., nl80211.
+	 *   ConfigFile(String) Configuration file path.
+	 *
+	 * @return Binder object representing the interface.
+	 */
+	IIface CreateInterface(in PersistableBundle args);
+
+	/**
+	 * Deregisters a wireless interface from wpa_supplicant.
+	 *
+	 * @param ifname Name of the network interface, e.g., wlan0
+	 */
+	void RemoveInterface(in @utf8InCpp String ifname);
+
+	/**
+	 * Gets a binder object for the interface corresponding to ifname
+	 * which wpa_supplicant already controls.
+	 *
+	 * @param ifname Name of the network interface, e.g., wlan0
+	 *
+	 * @return Binder object representing the interface.
+	 */
+	IIface GetInterface(in @utf8InCpp String ifname);
+}
diff --git a/wpa_supplicant/binder/fi/w1/wpa_supplicant/ISupplicantCallbacks.aidl b/wpa_supplicant/binder/fi/w1/wpa_supplicant/ISupplicantCallbacks.aidl
new file mode 100644
index 0000000..d624d91
--- /dev/null
+++ b/wpa_supplicant/binder/fi/w1/wpa_supplicant/ISupplicantCallbacks.aidl
@@ -0,0 +1,20 @@
+/*
+ * binder 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.
+ */
+
+package fi.w1.wpa_supplicant;
+
+import android.os.PersistableBundle;
+
+/**
+ * Callback Interface exposed by the wpa_supplicant service. Clients need
+ * to host an instance of this binder object and pass a reference of the object
+ * to wpa_supplicant via the registerCallbacksObject method.
+ */
+interface ISupplicantCallbacks {
+}
diff --git a/wpa_supplicant/binder/iface.cpp b/wpa_supplicant/binder/iface.cpp
new file mode 100644
index 0000000..af2548d
--- /dev/null
+++ b/wpa_supplicant/binder/iface.cpp
@@ -0,0 +1,19 @@
+/*
+ * binder 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 "iface.h"
+
+namespace wpa_supplicant_binder {
+
+Iface::Iface(struct wpa_supplicant *wpa_s)
+	: wpa_s_(wpa_s)
+{
+}
+
+} /* namespace wpa_supplicant_binder */
diff --git a/wpa_supplicant/binder/iface.h b/wpa_supplicant/binder/iface.h
new file mode 100644
index 0000000..acc8e55
--- /dev/null
+++ b/wpa_supplicant/binder/iface.h
@@ -0,0 +1,42 @@
+/*
+ * binder 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 IFACE_H
+#define IFACE_H
+
+#include "fi/w1/wpa_supplicant/BnIface.h"
+
+extern "C" {
+#include "utils/includes.h"
+#include "utils/common.h"
+#include "../wpa_supplicant_i.h"
+}
+
+namespace wpa_supplicant_binder {
+
+/**
+ * Implementation of Iface binder object. Each unique binder
+ * 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_supplicant *wpa_s);
+	virtual ~Iface() = default;
+
+private:
+	/* Raw pointer to the structure maintained by the core for this
+	 * interface. */
+	struct wpa_supplicant *wpa_s_;
+};
+
+} /* namespace wpa_supplicant_binder */
+
+#endif /* IFACE_H */
diff --git a/wpa_supplicant/binder/supplicant.cpp b/wpa_supplicant/binder/supplicant.cpp
new file mode 100644
index 0000000..6844e5a
--- /dev/null
+++ b/wpa_supplicant/binder/supplicant.cpp
@@ -0,0 +1,125 @@
+/*
+ * binder 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 "binder_manager.h"
+#include "supplicant.h"
+
+namespace wpa_supplicant_binder {
+
+Supplicant::Supplicant(struct wpa_global *global)
+	: wpa_global_(global)
+{
+}
+
+
+android::binder::Status Supplicant::CreateInterface(
+	const android::os::PersistableBundle &params,
+	android::sp<fi::w1::wpa_supplicant::IIface> *aidl_return)
+{
+	android::String16 driver, ifname, confname, bridge_ifname;
+
+	/* Check if required Ifname argument is missing */
+	if (!params.getString(android::String16("Ifname"), &ifname))
+		return android::binder::Status::fromServiceSpecificError(
+			ERROR_INVALID_ARGS,
+			android::String8("Ifname missing in params."));
+	/* Retrieve the remaining params from the dictionary */
+	params.getString(android::String16("Driver"), &driver);
+	params.getString(android::String16("ConfigFile"), &confname);
+	params.getString(android::String16("BridgeIfname"), &bridge_ifname);
+
+	/*
+	 * 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_,
+				     android::String8(ifname).string()) != NULL)
+		return android::binder::Status::fromServiceSpecificError(
+			ERROR_IFACE_EXISTS,
+			android::String8("wpa_supplicant already controls this interface."));
+
+	android::binder::Status status;
+	struct wpa_supplicant *wpa_s = NULL;
+	struct wpa_interface iface;
+
+	os_memset(&iface, 0, sizeof(iface));
+	iface.driver = os_strdup(android::String8(driver).string());
+	iface.ifname = os_strdup(android::String8(ifname).string());
+	iface.confname = os_strdup(android::String8(confname).string());
+	iface.bridge_ifname = os_strdup(
+		android::String8(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 binder object via
+	 * BinderManager when |wpa_supplicant_add_iface| is called. */
+	if (!wpa_s || !wpa_s->binder_object_key) {
+		status = android::binder::Status::fromServiceSpecificError(
+			ERROR_UNKNOWN,
+			android::String8("wpa_supplicant couldn't grab this interface."));
+	} else {
+		BinderManager *binder_manager = BinderManager::getInstance();
+
+		if (!binder_manager ||
+		    binder_manager->getIfaceBinderObjectByKey(
+			    wpa_s->binder_object_key, aidl_return))
+			status = android::binder::Status::fromServiceSpecificError(
+				ERROR_UNKNOWN,
+				android::String8("wpa_supplicant encountered a binder error."));
+		else
+			status = android::binder::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::binder::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 || !wpa_s->binder_object_key)
+		return android::binder::Status::fromServiceSpecificError(
+			ERROR_IFACE_UNKNOWN,
+			android::String8("wpa_supplicant does not control this interface."));
+	if (wpa_supplicant_remove_iface(wpa_global_, wpa_s, 0))
+		return android::binder::Status::fromServiceSpecificError(
+			ERROR_UNKNOWN,
+			android::String8("wpa_supplicant couldn't remove this interface."));
+	return android::binder::Status::ok();
+}
+
+
+android::binder::Status Supplicant::GetInterface(
+	const std::string &ifname,
+	android::sp<fi::w1::wpa_supplicant::IIface> *aidl_return)
+{
+	struct wpa_supplicant *wpa_s;
+
+	wpa_s = wpa_supplicant_get_iface(wpa_global_, ifname.c_str());
+	if (!wpa_s || !wpa_s->binder_object_key)
+		return android::binder::Status::fromServiceSpecificError(
+			ERROR_IFACE_UNKNOWN,
+			android::String8("wpa_supplicant does not control this interface."));
+
+	BinderManager *binder_manager = BinderManager::getInstance();
+	if (!binder_manager ||
+	    binder_manager->getIfaceBinderObjectByKey(wpa_s->binder_object_key,
+						      aidl_return))
+		return android::binder::Status::fromServiceSpecificError(
+			ERROR_UNKNOWN,
+			android::String8("wpa_supplicant encountered a binder error."));
+
+	return android::binder::Status::ok();
+}
+
+} /* namespace wpa_supplicant_binder */
diff --git a/wpa_supplicant/binder/supplicant.h b/wpa_supplicant/binder/supplicant.h
new file mode 100644
index 0000000..b96f4e6
--- /dev/null
+++ b/wpa_supplicant/binder/supplicant.h
@@ -0,0 +1,57 @@
+/*
+ * binder 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 SUPPLICANT_H
+#define SUPPLICANT_H
+
+#include "fi/w1/wpa_supplicant/BnSupplicant.h"
+#include "fi/w1/wpa_supplicant/IIface.h"
+#include "fi/w1/wpa_supplicant/ISupplicantCallbacks.h"
+
+extern "C" {
+#include "utils/includes.h"
+#include "utils/common.h"
+#include "../wpa_supplicant_i.h"
+}
+
+namespace wpa_supplicant_binder {
+
+/**
+ * Implementation of the supplicant binder object. This binder
+ * 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);
+	virtual ~Supplicant() = default;
+
+	android::binder::Status CreateInterface(
+		const android::os::PersistableBundle &params,
+		android::sp<fi::w1::wpa_supplicant::IIface> *aidl_return)
+		override;
+	android::binder::Status RemoveInterface(
+		const std::string &ifname) override;
+	android::binder::Status GetInterface(
+		const std::string &ifname,
+		android::sp<fi::w1::wpa_supplicant::IIface> *aidl_return)
+		override;
+
+private:
+	/* 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::ISupplicantCallbacks>>
+		callbacks_;
+};
+
+} /* namespace wpa_supplicant_binder */
+
+#endif /* SUPPLICANT_H */