Merge "Merge Android Pie into master"
diff --git a/hostapd/Android.mk b/hostapd/Android.mk
index a9ded3c..54d12f6 100644
--- a/hostapd/Android.mk
+++ b/hostapd/Android.mk
@@ -46,11 +46,11 @@
 endif
 
 # Use Android specific directory for control interface sockets
-L_CFLAGS += -DCONFIG_CTRL_IFACE_CLIENT_DIR=\"/data/misc/wifi/sockets\"
-L_CFLAGS += -DCONFIG_CTRL_IFACE_DIR=\"/data/system/hostapd\"
+L_CFLAGS += -DCONFIG_CTRL_IFACE_CLIENT_DIR=\"/data/vendor/wifi/hostapd/sockets\"
+L_CFLAGS += -DCONFIG_CTRL_IFACE_DIR=\"/data/vendor/wifi/hostapd/ctrl\"
 
 # Use Android specific directory for hostapd_cli command completion history
-L_CFLAGS += -DCONFIG_HOSTAPD_CLI_HISTORY_DIR=\"/data/misc/wifi\"
+L_CFLAGS += -DCONFIG_HOSTAPD_CLI_HISTORY_DIR=\"/data/vendor/wifi/hostapd\"
 
 # To force sizeof(enum) = 4
 ifeq ($(TARGET_ARCH),arm)
@@ -1072,6 +1072,14 @@
 OBJS_c += src/utils/edit_simple.c
 endif
 
+ifeq ($(filter gce_x86 gce_x86_64 calypso generic_x86 generic_x86_64 generic generic_arm64, $(TARGET_DEVICE)),)
+ifdef CONFIG_CTRL_IFACE_HIDL
+HOSTAPD_USE_HIDL=y
+L_CFLAGS += -DCONFIG_CTRL_IFACE_HIDL
+L_CPPFLAGS = -Wall -Werror
+endif
+endif
+
 ########################
 
 include $(CLEAR_VARS)
@@ -1089,6 +1097,7 @@
 LOCAL_MODULE := hostapd
 LOCAL_MODULE_TAGS := optional
 LOCAL_PROPRIETARY_MODULE := true
+LOCAL_MODULE_RELATIVE_PATH := hw
 ifdef CONFIG_DRIVER_CUSTOM
 LOCAL_STATIC_LIBRARIES := libCustomWifi
 endif
@@ -1103,10 +1112,40 @@
 LOCAL_STATIC_LIBRARIES += libnl_2
 endif
 endif
+ifeq ($(HOSTAPD_USE_HIDL), y)
+LOCAL_SHARED_LIBRARIES += android.hardware.wifi.hostapd@1.0
+LOCAL_SHARED_LIBRARIES += libbase libhidlbase libhidltransport libhwbinder libutils
+LOCAL_STATIC_LIBRARIES += libhostapd_hidl
+endif
 LOCAL_CFLAGS := $(L_CFLAGS)
 LOCAL_SRC_FILES := $(OBJS)
 LOCAL_C_INCLUDES := $(INCLUDES)
 LOCAL_INIT_RC := hostapd.android.rc
 include $(BUILD_EXECUTABLE)
 
+ifeq ($(HOSTAPD_USE_HIDL), y)
+### Hidl service library ###
+########################
+include $(CLEAR_VARS)
+LOCAL_MODULE := libhostapd_hidl
+LOCAL_VENDOR_MODULE := true
+LOCAL_CPPFLAGS := $(L_CPPFLAGS)
+LOCAL_CFLAGS := $(L_CFLAGS)
+LOCAL_C_INCLUDES := $(INCLUDES)
+HIDL_INTERFACE_VERSION = 1.0
+LOCAL_SRC_FILES := \
+    hidl/$(HIDL_INTERFACE_VERSION)/hidl.cpp \
+    hidl/$(HIDL_INTERFACE_VERSION)/hostapd.cpp
+LOCAL_SHARED_LIBRARIES := \
+    android.hardware.wifi.hostapd@1.0 \
+    libbase \
+    libhidlbase \
+    libhidltransport \
+    libhwbinder \
+    libutils \
+    liblog
+LOCAL_EXPORT_C_INCLUDE_DIRS := \
+    $(LOCAL_PATH)/hidl/$(HIDL_INTERFACE_VERSION)
+include $(BUILD_STATIC_LIBRARY)
+endif # HOSTAPD_USE_HIDL == y
 endif # ifeq ($(WPA_BUILD_HOSTAPD),true)
diff --git a/hostapd/CleanSpec.mk b/hostapd/CleanSpec.mk
index 653aebb..5d50cd4 100644
--- a/hostapd/CleanSpec.mk
+++ b/hostapd/CleanSpec.mk
@@ -49,4 +49,5 @@
 # NEWER CLEAN STEPS MUST BE AT THE END OF THE LIST
 # ************************************************
 $(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/bin/hostapd)
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/vendor/bin/hostapd)
 $(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/bin/hostapd_cli)
diff --git a/hostapd/android.config b/hostapd/android.config
index 08d21f0..5a24438 100644
--- a/hostapd/android.config
+++ b/hostapd/android.config
@@ -134,6 +134,9 @@
 # IEEE 802.11n (High Throughput) support
 CONFIG_IEEE80211N=y
 
+# IEEE 802.11ac (Very High Throughput) support
+CONFIG_IEEE80211AC=y
+
 # Remove debugging code that is printing out debug messages to stdout.
 # This can be used to reduce the size of the hostapd considerably if debugging
 # code is not needed.
@@ -210,3 +213,10 @@
 # /dev/urandom earlier in boot' seeds /dev/urandom with that entropy before
 # either wpa_supplicant or hostapd are run.
 CONFIG_NO_RANDOM_POOL=y
+
+# Add support for Hidl control interface
+# Only applicable for Android platforms.
+CONFIG_CTRL_IFACE_HIDL=y
+
+# Enable support of Automatic Channel Selection
+CONFIG_ACS=y
diff --git a/hostapd/hidl/.clang-format b/hostapd/hidl/.clang-format
new file mode 100644
index 0000000..42fadb5
--- /dev/null
+++ b/hostapd/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/hostapd/hidl/1.0/hidl.cpp b/hostapd/hidl/1.0/hidl.cpp
new file mode 100644
index 0000000..a0dc50e
--- /dev/null
+++ b/hostapd/hidl/1.0/hidl.cpp
@@ -0,0 +1,70 @@
+/*
+ * hidl interface for wpa_supplicant daemon
+ * Copyright (c) 2004-2018, Jouni Malinen <j@w1.fi>
+ * Copyright (c) 2004-2018, Roshan Pius <rpius@google.com>
+ *
+ * This software may be distributed under the terms of the BSD license.
+ * See README for more details.
+ */
+
+#include <hwbinder/IPCThreadState.h>
+#include <hidl/HidlTransportSupport.h>
+
+#include "hostapd.h"
+
+extern "C"
+{
+#include "hidl.h"
+#include "utils/common.h"
+#include "utils/eloop.h"
+#include "utils/includes.h"
+}
+
+using android::hardware::configureRpcThreadpool;
+using android::hardware::IPCThreadState;
+using android::hardware::wifi::hostapd::V1_0::IHostapd;
+using android::hardware::wifi::hostapd::V1_0::implementation::Hostapd;
+
+// This file is a bridge between the hostapd code written in 'C' and the HIDL
+// interface in C++. So, using "C" style static globals here!
+static int hidl_fd = -1;
+static android::sp<IHostapd> service;
+
+void hostapd_hidl_sock_handler(
+    int /* sock */, void * /* eloop_ctx */, void * /* sock_ctx */)
+{
+	IPCThreadState::self()->handlePolledCommands();
+}
+
+int hostapd_hidl_init(struct hapd_interfaces *interfaces)
+{
+	wpa_printf(MSG_DEBUG, "Initing hidl control");
+
+	IPCThreadState::self()->setupPolling(&hidl_fd);
+	if (hidl_fd < 0)
+		goto err;
+
+	wpa_printf(MSG_INFO, "Processing hidl events on FD %d", hidl_fd);
+	// Look for read events from the hidl socket in the eloop.
+	if (eloop_register_read_sock(
+		hidl_fd, hostapd_hidl_sock_handler, interfaces, NULL) < 0)
+		goto err;
+	service = new Hostapd(interfaces);
+	if (!service)
+		goto err;
+	if (service->registerAsService() != android::NO_ERROR)
+		goto err;
+	return 0;
+err:
+	hostapd_hidl_deinit(interfaces);
+	return -1;
+}
+
+void hostapd_hidl_deinit(struct hapd_interfaces *interfaces)
+{
+	wpa_printf(MSG_DEBUG, "Deiniting hidl control");
+	eloop_unregister_read_sock(hidl_fd);
+	IPCThreadState::shutdown();
+	hidl_fd = -1;
+	service.clear();
+}
diff --git a/hostapd/hidl/1.0/hidl.h b/hostapd/hidl/1.0/hidl.h
new file mode 100644
index 0000000..5decf64
--- /dev/null
+++ b/hostapd/hidl/1.0/hidl.h
@@ -0,0 +1,30 @@
+/*
+ * hidl interface for wpa_supplicant daemon
+ * Copyright (c) 2004-2018, Jouni Malinen <j@w1.fi>
+ * Copyright (c) 2004-2018, Roshan Pius <rpius@google.com>
+ *
+ * This software may be distributed under the terms of the BSD license.
+ * See README for more details.
+ */
+
+#ifndef HOSTAPD_HIDL_HIDL_H
+#define HOSTAPD_HIDL_HIDL_H
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif  // _cplusplus
+#include "ap/hostapd.h"
+
+/**
+ * This is the hidl RPC interface entry point to the hostapd core.
+ * This initializes the hidl driver & IHostapd instance.
+ */
+int hostapd_hidl_init(struct hapd_interfaces *interfaces);
+void hostapd_hidl_deinit(struct hapd_interfaces *interfaces);
+
+#ifdef __cplusplus
+}
+#endif  // _cplusplus
+
+#endif  // HOSTAPD_HIDL_HIDL_H
diff --git a/hostapd/hidl/1.0/hidl_return_util.h b/hostapd/hidl/1.0/hidl_return_util.h
new file mode 100644
index 0000000..1625dc2
--- /dev/null
+++ b/hostapd/hidl/1.0/hidl_return_util.h
@@ -0,0 +1,44 @@
+/*
+ * hidl interface for wpa_hostapd daemon
+ * Copyright (c) 2004-2018, Jouni Malinen <j@w1.fi>
+ * Copyright (c) 2004-2018, Roshan Pius <rpius@google.com>
+ *
+ * This software may be distributed under the terms of the BSD license.
+ * See README for more details.
+ */
+
+#ifndef HIDL_RETURN_UTIL_H_
+#define HIDL_RETURN_UTIL_H_
+
+#include <functional>
+
+namespace android {
+namespace hardware {
+namespace wifi {
+namespace hostapd {
+namespace V1_0 {
+namespace implementation {
+namespace hidl_return_util {
+
+/**
+ * These utility functions are used to invoke a method on the provided
+ * HIDL interface object.
+ */
+// Use for HIDL methods which return only an instance of HostapdStatus.
+template <typename ObjT, typename WorkFuncT, typename... Args>
+Return<void> call(
+    ObjT* obj, WorkFuncT&& work,
+    const std::function<void(const HostapdStatus&)>& hidl_cb, Args&&... args)
+{
+	hidl_cb((obj->*work)(std::forward<Args>(args)...));
+	return Void();
+}
+
+}  // namespace hidl_return_util
+}  // namespace implementation
+}  // namespace V1_0
+}  // namespace hostapd
+}  // namespace wifi
+}  // namespace hardware
+}  // namespace android
+#endif  // HIDL_RETURN_UTIL_H_
diff --git a/hostapd/hidl/1.0/hostapd.cpp b/hostapd/hidl/1.0/hostapd.cpp
new file mode 100644
index 0000000..3cd78b3
--- /dev/null
+++ b/hostapd/hidl/1.0/hostapd.cpp
@@ -0,0 +1,286 @@
+/*
+ * hidl interface for wpa_hostapd daemon
+ * Copyright (c) 2004-2018, Jouni Malinen <j@w1.fi>
+ * Copyright (c) 2004-2018, Roshan Pius <rpius@google.com>
+ *
+ * This software may be distributed under the terms of the BSD license.
+ * See README for more details.
+ */
+#include <iomanip>
+#include <sstream>
+#include <string>
+#include <vector>
+
+#include <android-base/file.h>
+#include <android-base/stringprintf.h>
+
+#include "hostapd.h"
+#include "hidl_return_util.h"
+
+extern "C"
+{
+#include "utils/eloop.h"
+}
+
+// The HIDL implementation for hostapd creates a hostapd.conf dynamically for
+// each interface. This file can then be used to hook onto the normal config
+// file parsing logic in hostapd code.  Helps us to avoid duplication of code
+// in the HIDL interface.
+// TOOD(b/71872409): Add unit tests for this.
+namespace {
+constexpr char kConfFileNameFmt[] = "/data/vendor/wifi/hostapd/hostapd_%s.conf";
+
+using android::base::RemoveFileIfExists;
+using android::base::StringPrintf;
+using android::base::WriteStringToFile;
+using android::hardware::wifi::hostapd::V1_0::IHostapd;
+
+std::string WriteHostapdConfig(
+    const std::string& interface_name, const std::string& config)
+{
+	const std::string file_path =
+	    StringPrintf(kConfFileNameFmt, interface_name.c_str());
+	if (WriteStringToFile(
+		config, file_path, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP,
+		getuid(), getgid())) {
+		return file_path;
+	}
+	// Diagnose failure
+	int error = errno;
+	wpa_printf(
+	    MSG_ERROR, "Cannot write hostapd config to %s, error: %s",
+	    file_path.c_str(), strerror(error));
+	struct stat st;
+	int result = stat(file_path.c_str(), &st);
+	if (result == 0) {
+		wpa_printf(
+		    MSG_ERROR, "hostapd config file uid: %d, gid: %d, mode: %d",
+		    st.st_uid, st.st_gid, st.st_mode);
+	} else {
+		wpa_printf(
+		    MSG_ERROR,
+		    "Error calling stat() on hostapd config file: %s",
+		    strerror(errno));
+	}
+	return "";
+}
+
+std::string CreateHostapdConfig(
+    const IHostapd::IfaceParams& iface_params,
+    const IHostapd::NetworkParams& nw_params)
+{
+	if (nw_params.ssid.size() >
+	    static_cast<uint32_t>(
+		IHostapd::ParamSizeLimits::SSID_MAX_LEN_IN_BYTES)) {
+		wpa_printf(
+		    MSG_ERROR, "Invalid SSID size: %zu", nw_params.ssid.size());
+		return "";
+	}
+	if ((nw_params.encryptionType != IHostapd::EncryptionType::NONE) &&
+	    (nw_params.pskPassphrase.size() <
+		 static_cast<uint32_t>(
+		     IHostapd::ParamSizeLimits::
+			 WPA2_PSK_PASSPHRASE_MIN_LEN_IN_BYTES) ||
+	     nw_params.pskPassphrase.size() >
+		 static_cast<uint32_t>(
+		     IHostapd::ParamSizeLimits::
+			 WPA2_PSK_PASSPHRASE_MAX_LEN_IN_BYTES))) {
+		wpa_printf(
+		    MSG_ERROR, "Invalid psk passphrase size: %zu",
+		    nw_params.pskPassphrase.size());
+		return "";
+	}
+
+	// SSID string
+	std::stringstream ss;
+	ss << std::hex;
+	ss << std::setfill('0');
+	for (uint8_t b : nw_params.ssid) {
+		ss << std::setw(2) << static_cast<unsigned int>(b);
+	}
+	const std::string ssid_as_string = ss.str();
+
+	// Encryption config string
+	std::string encryption_config_as_string;
+	switch (nw_params.encryptionType) {
+	case IHostapd::EncryptionType::NONE:
+		// no security params
+		break;
+	case IHostapd::EncryptionType::WPA:
+		encryption_config_as_string = StringPrintf(
+		    "wpa=3\n"
+		    "wpa_pairwise=TKIP CCMP\n"
+		    "wpa_passphrase=%s",
+		    nw_params.pskPassphrase.c_str());
+		break;
+	case IHostapd::EncryptionType::WPA2:
+		encryption_config_as_string = StringPrintf(
+		    "wpa=2\n"
+		    "rsn_pairwise=CCMP\n"
+		    "wpa_passphrase=%s",
+		    nw_params.pskPassphrase.c_str());
+		break;
+	default:
+		wpa_printf(MSG_ERROR, "Unknown encryption type");
+		return "";
+	}
+
+	std::string channel_config_as_string;
+	if (iface_params.channelParams.enableAcs) {
+		channel_config_as_string = StringPrintf(
+		    "channel=0\n"
+		    "acs_exclude_dfs=%d",
+		    iface_params.channelParams.acsShouldExcludeDfs);
+	} else {
+		channel_config_as_string = StringPrintf(
+		    "channel=%d", iface_params.channelParams.channel);
+	}
+
+	// Hw Mode String
+	std::string hw_mode_as_string;
+	std::string ht_cap_vht_oper_chwidth_as_string;
+	switch (iface_params.channelParams.band) {
+	case IHostapd::Band::BAND_2_4_GHZ:
+		hw_mode_as_string = "hw_mode=g";
+		break;
+	case IHostapd::Band::BAND_5_GHZ:
+		hw_mode_as_string = "hw_mode=a";
+		if (iface_params.channelParams.enableAcs) {
+			ht_cap_vht_oper_chwidth_as_string =
+			    "ht_capab=[HT40+]\n"
+			    "vht_oper_chwidth=1";
+		}
+		break;
+	case IHostapd::Band::BAND_ANY:
+		hw_mode_as_string = "hw_mode=any";
+		if (iface_params.channelParams.enableAcs) {
+			ht_cap_vht_oper_chwidth_as_string =
+			    "ht_capab=[HT40+]\n"
+			    "vht_oper_chwidth=1";
+		}
+		break;
+	default:
+		wpa_printf(MSG_ERROR, "Invalid band");
+		return "";
+	}
+
+	return StringPrintf(
+	    "interface=%s\n"
+	    "driver=nl80211\n"
+	    "ctrl_interface=/data/vendor/wifi/hostapd/ctrl\n"
+	    // ssid2 signals to hostapd that the value is not a literal value
+	    // for use as a SSID.  In this case, we're giving it a hex
+	    // std::string and hostapd needs to expect that.
+	    "ssid2=%s\n"
+	    "%s\n"
+	    "ieee80211n=%d\n"
+	    "ieee80211ac=%d\n"
+	    "%s\n"
+	    "%s\n"
+	    "ignore_broadcast_ssid=%d\n"
+	    "wowlan_triggers=any\n"
+	    "%s\n",
+	    iface_params.ifaceName.c_str(), ssid_as_string.c_str(),
+	    channel_config_as_string.c_str(),
+	    iface_params.hwModeParams.enable80211N ? 1 : 0,
+	    iface_params.hwModeParams.enable80211AC ? 1 : 0,
+	    hw_mode_as_string.c_str(), ht_cap_vht_oper_chwidth_as_string.c_str(),
+	    nw_params.isHidden ? 1 : 0, encryption_config_as_string.c_str());
+}
+}  // namespace
+
+namespace android {
+namespace hardware {
+namespace wifi {
+namespace hostapd {
+namespace V1_0 {
+namespace implementation {
+using hidl_return_util::call;
+
+Hostapd::Hostapd(struct hapd_interfaces* interfaces) : interfaces_(interfaces)
+{}
+
+Return<void> Hostapd::addAccessPoint(
+    const IfaceParams& iface_params, const NetworkParams& nw_params,
+    addAccessPoint_cb _hidl_cb)
+{
+	return call(
+	    this, &Hostapd::addAccessPointInternal, _hidl_cb, iface_params,
+	    nw_params);
+}
+
+Return<void> Hostapd::removeAccessPoint(
+    const hidl_string& iface_name, removeAccessPoint_cb _hidl_cb)
+{
+	return call(
+	    this, &Hostapd::removeAccessPointInternal, _hidl_cb, iface_name);
+}
+
+Return<void> Hostapd::terminate() {
+	wpa_printf(MSG_INFO, "Terminating...");
+	eloop_terminate();
+	return Void();
+}
+
+HostapdStatus Hostapd::addAccessPointInternal(
+    const IfaceParams& iface_params, const NetworkParams& nw_params)
+{
+	if (hostapd_get_iface(interfaces_, iface_params.ifaceName.c_str())) {
+		wpa_printf(
+		    MSG_ERROR, "Interface %s already present",
+		    iface_params.ifaceName.c_str());
+		return {HostapdStatusCode::FAILURE_IFACE_EXISTS, ""};
+	}
+	const auto conf_params = CreateHostapdConfig(iface_params, nw_params);
+	if (conf_params.empty()) {
+		wpa_printf(MSG_ERROR, "Failed to create config params");
+		return {HostapdStatusCode::FAILURE_ARGS_INVALID, ""};
+	}
+	const auto conf_file_path =
+	    WriteHostapdConfig(iface_params.ifaceName, conf_params);
+	if (conf_file_path.empty()) {
+		wpa_printf(MSG_ERROR, "Failed to write config file");
+		return {HostapdStatusCode::FAILURE_UNKNOWN, ""};
+	}
+	std::string add_iface_param_str = StringPrintf(
+	    "%s config=%s", iface_params.ifaceName.c_str(),
+	    conf_file_path.c_str());
+	std::vector<char> add_iface_param_vec(
+	    add_iface_param_str.begin(), add_iface_param_str.end() + 1);
+	if (hostapd_add_iface(interfaces_, add_iface_param_vec.data()) < 0) {
+		wpa_printf(
+		    MSG_ERROR, "Adding interface %s failed",
+		    add_iface_param_str.c_str());
+		return {HostapdStatusCode::FAILURE_UNKNOWN, ""};
+	}
+	struct hostapd_data* iface_hapd =
+	    hostapd_get_iface(interfaces_, iface_params.ifaceName.c_str());
+	WPA_ASSERT(iface_hapd != nullptr && iface_hapd->iface != nullptr);
+	if (hostapd_enable_iface(iface_hapd->iface) < 0) {
+		wpa_printf(
+		    MSG_ERROR, "Enabling interface %s failed",
+		    iface_params.ifaceName.c_str());
+		return {HostapdStatusCode::FAILURE_UNKNOWN, ""};
+	}
+	return {HostapdStatusCode::SUCCESS, ""};
+}
+
+HostapdStatus Hostapd::removeAccessPointInternal(const std::string& iface_name)
+{
+	std::vector<char> remove_iface_param_vec(
+	    iface_name.begin(), iface_name.end() + 1);
+	if (hostapd_remove_iface(interfaces_, remove_iface_param_vec.data()) <
+	    0) {
+		wpa_printf(
+		    MSG_ERROR, "Removing interface %s failed",
+		    iface_name.c_str());
+		return {HostapdStatusCode::FAILURE_UNKNOWN, ""};
+	}
+	return {HostapdStatusCode::SUCCESS, ""};
+}
+}  // namespace implementation
+}  // namespace V1_0
+}  // namespace hostapd
+}  // namespace wifi
+}  // namespace hardware
+}  // namespace android
diff --git a/hostapd/hidl/1.0/hostapd.h b/hostapd/hidl/1.0/hostapd.h
new file mode 100644
index 0000000..7985fd9
--- /dev/null
+++ b/hostapd/hidl/1.0/hostapd.h
@@ -0,0 +1,72 @@
+/*
+ * hidl interface for wpa_hostapd daemon
+ * Copyright (c) 2004-2018, Jouni Malinen <j@w1.fi>
+ * Copyright (c) 2004-2018, Roshan Pius <rpius@google.com>
+ *
+ * This software may be distributed under the terms of the BSD license.
+ * See README for more details.
+ */
+
+#ifndef HOSTAPD_HIDL_SUPPLICANT_H
+#define HOSTAPD_HIDL_SUPPLICANT_H
+
+#include <string>
+
+#include <android-base/macros.h>
+
+#include <android/hardware/wifi/hostapd/1.0/IHostapd.h>
+
+extern "C"
+{
+#include "utils/common.h"
+#include "utils/includes.h"
+#include "utils/wpa_debug.h"
+#include "ap/hostapd.h"
+}
+
+namespace android {
+namespace hardware {
+namespace wifi {
+namespace hostapd {
+namespace V1_0 {
+namespace implementation {
+
+/**
+ * Implementation of the hostapd hidl object. This hidl
+ * object is used core for global control operations on
+ * hostapd.
+ */
+class Hostapd : public V1_0::IHostapd
+{
+public:
+	Hostapd(hapd_interfaces* interfaces);
+	~Hostapd() override = default;
+
+	// Hidl methods exposed.
+	Return<void> addAccessPoint(
+	    const IfaceParams& iface_params, const NetworkParams& nw_params,
+	    addAccessPoint_cb _hidl_cb) override;
+	Return<void> removeAccessPoint(
+	    const hidl_string& iface_name,
+	    removeAccessPoint_cb _hidl_cb) override;
+	Return<void> terminate() override;
+
+private:
+	// Corresponding worker functions for the HIDL methods.
+	HostapdStatus addAccessPointInternal(
+	    const IfaceParams& iface_params, const NetworkParams& nw_params);
+	HostapdStatus removeAccessPointInternal(const std::string& iface_name);
+
+	// Raw pointer to the global structure maintained by the core.
+	struct hapd_interfaces* interfaces_;
+
+	DISALLOW_COPY_AND_ASSIGN(Hostapd);
+};
+}  // namespace implementation
+}  // namespace V1_0
+}  // namespace hostapd
+}  // namespace wifi
+}  // namespace hardware
+}  // namespace android
+
+#endif  // HOSTAPD_HIDL_SUPPLICANT_H
diff --git a/hostapd/hostapd.android.rc b/hostapd/hostapd.android.rc
index 048c667..37a95c2 100644
--- a/hostapd/hostapd.android.rc
+++ b/hostapd/hostapd.android.rc
@@ -7,14 +7,15 @@
 #
 
 on post-fs-data
-    mkdir /data/misc/wifi/hostapd 0770 wifi wifi
+    mkdir /data/vendor/wifi 0770 wifi wifi
+    mkdir /data/vendor/wifi/hostapd 0770 wifi wifi
+    mkdir /data/vendor/wifi/hostapd/sockets 0770 wifi wifi
 
-service hostapd /vendor/bin/hostapd \
-        /data/misc/wifi/hostapd.conf
+service hostapd /vendor/bin/hw/hostapd
+    interface android.hardware.wifi.hostapd@1.0::IHostapd default
     class main
     capabilities NET_ADMIN NET_RAW
     user wifi
     group wifi net_raw net_admin
-    writepid /data/misc/wifi/hostapd.pid
     disabled
     oneshot
diff --git a/hostapd/main.c b/hostapd/main.c
index ce94d05..6c0490f 100644
--- a/hostapd/main.c
+++ b/hostapd/main.c
@@ -28,7 +28,9 @@
 #include "config_file.h"
 #include "eap_register.h"
 #include "ctrl_iface.h"
-
+#ifdef CONFIG_CTRL_IFACE_HIDL
+#include "hidl.h"
+#endif /* CONFIG_CTRL_IFACE_HIDL */
 
 struct hapd_global {
 	void **drv_priv;
@@ -751,9 +753,11 @@
 		}
 	}
 
+#ifndef CONFIG_CTRL_IFACE_HIDL
 	if (optind == argc && interfaces.global_iface_path == NULL &&
 	    num_bss_configs == 0)
 		usage();
+#endif
 
 	wpa_msg_register_ifname_cb(hostapd_msg_ifname_cb);
 
@@ -893,6 +897,12 @@
 			goto out;
 	}
 
+#ifdef CONFIG_CTRL_IFACE_HIDL
+	if (hostapd_hidl_init(&interfaces)) {
+		wpa_printf(MSG_ERROR, "Failed to initialize HIDL interface");
+		goto out;
+	}
+#endif /* CONFIG_CTRL_IFACE_HIDL */
 	hostapd_global_ctrl_iface_init(&interfaces);
 
 	if (hostapd_global_run(&interfaces, daemonize, pid_file)) {
@@ -903,6 +913,9 @@
 	ret = 0;
 
  out:
+#ifdef CONFIG_CTRL_IFACE_HIDL
+	hostapd_hidl_deinit(&interfaces);
+#endif /* CONFIG_CTRL_IFACE_HIDL */
 	hostapd_global_ctrl_iface_deinit(&interfaces);
 	/* Deinitialize all interfaces */
 	for (i = 0; i < interfaces.count; i++) {
diff --git a/src/ap/hostapd.h b/src/ap/hostapd.h
index f77e6ec..d7c6720 100644
--- a/src/ap/hostapd.h
+++ b/src/ap/hostapd.h
@@ -372,6 +372,16 @@
 #endif /* CONFIG_TAXONOMY */
 };
 
+enum hostapd_iface_state {
+	HAPD_IFACE_UNINITIALIZED,
+	HAPD_IFACE_DISABLED,
+	HAPD_IFACE_COUNTRY_UPDATE,
+	HAPD_IFACE_ACS,
+	HAPD_IFACE_HT_SCAN,
+	HAPD_IFACE_DFS,
+	HAPD_IFACE_ENABLED
+};
+
 /**
  * struct hostapd_iface - hostapd per-interface data structure
  */
@@ -382,16 +392,7 @@
 	struct hostapd_config *conf;
 	char phy[16]; /* Name of the PHY (radio) */
 
-	enum hostapd_iface_state {
-		HAPD_IFACE_UNINITIALIZED,
-		HAPD_IFACE_DISABLED,
-		HAPD_IFACE_COUNTRY_UPDATE,
-		HAPD_IFACE_ACS,
-		HAPD_IFACE_HT_SCAN,
-		HAPD_IFACE_DFS,
-		HAPD_IFACE_ENABLED
-	} state;
-
+        enum hostapd_iface_state state;
 #ifdef CONFIG_MESH
 	struct mesh_conf *mconf;
 #endif /* CONFIG_MESH */
diff --git a/src/crypto/tls_openssl.c b/src/crypto/tls_openssl.c
index 988c9d2..7243d9f 100644
--- a/src/crypto/tls_openssl.c
+++ b/src/crypto/tls_openssl.c
@@ -116,6 +116,20 @@
 #include <openssl/pem.h>
 #include <keystore/keystore_get.h>
 
+#include <log/log.h>
+#include <log/log_event_list.h>
+
+#define CERT_VALIDATION_FAILURE 210033
+
+static void log_cert_validation_failure(const char *reason)
+{
+	android_log_context ctx = create_android_logger(CERT_VALIDATION_FAILURE);
+	android_log_write_string8(ctx, reason);
+	android_log_write_list(ctx, LOG_ID_SECURITY);
+	android_log_destroy(&ctx);
+}
+
+
 static BIO * BIO_from_keystore(const char *key)
 {
 	BIO *bio = NULL;
@@ -1787,6 +1801,10 @@
 	struct wpabuf *cert = NULL;
 	struct tls_context *context = conn->context;
 
+#ifdef ANDROID
+	log_cert_validation_failure(err_str);
+#endif
+
 	if (context->event_cb == NULL)
 		return;
 
diff --git a/src/eap_peer/eap.c b/src/eap_peer/eap.c
index 0043707..52b0491 100644
--- a/src/eap_peer/eap.c
+++ b/src/eap_peer/eap.c
@@ -94,6 +94,12 @@
 		sm->eapol_cb->notify_status(sm->eapol_ctx, status, parameter);
 }
 
+static void eap_report_error(struct eap_sm *sm, int error_code)
+{
+	wpa_printf(MSG_DEBUG, "EAP: Error notification: %d", error_code);
+	if (sm->eapol_cb->notify_eap_error)
+		sm->eapol_cb->notify_eap_error(sm->eapol_ctx, error_code);
+}
 
 static void eap_sm_free_key(struct eap_sm *sm)
 {
@@ -1934,6 +1940,7 @@
 	const struct eap_hdr *hdr;
 	size_t plen;
 	const u8 *pos;
+        int error_code;
 
 	sm->rxReq = sm->rxResp = sm->rxSuccess = sm->rxFailure = FALSE;
 	sm->reqId = 0;
@@ -2018,6 +2025,13 @@
 	case EAP_CODE_FAILURE:
 		wpa_printf(MSG_DEBUG, "EAP: Received EAP-Failure");
 		eap_notify_status(sm, "completion", "failure");
+
+		/* Get the error code from method */
+		if (sm->m && sm->m->get_error_code) {
+			error_code = sm->m->get_error_code(sm->eap_method_priv);
+			if (error_code != NO_EAP_METHOD_ERROR)
+				eap_report_error(sm, error_code);
+		}
 		sm->rxFailure = TRUE;
 		break;
 	case EAP_CODE_INITIATE:
diff --git a/src/eap_peer/eap.h b/src/eap_peer/eap.h
index b5591a0..d0837e3 100644
--- a/src/eap_peer/eap.h
+++ b/src/eap_peer/eap.h
@@ -246,6 +246,13 @@
 	void (*notify_status)(void *ctx, const char *status,
 			      const char *parameter);
 
+	/**
+	 * notify_eap_error - Report EAP method error code
+	 * @ctx: eapol_ctx from eap_peer_sm_init() call
+	 * @error_code: Error code from the used EAP method
+	 */
+	void (*notify_eap_error)(void *ctx, int error_code);
+
 #ifdef CONFIG_EAP_PROXY
 	/**
 	 * eap_proxy_cb - Callback signifying any updates from eap_proxy
diff --git a/src/eap_peer/eap_aka.c b/src/eap_peer/eap_aka.c
index f7e3cd6..679f101 100644
--- a/src/eap_peer/eap_aka.c
+++ b/src/eap_peer/eap_aka.c
@@ -56,6 +56,7 @@
 	int kdf_negotiation;
 	u16 last_kdf_attrs[EAP_AKA_PRIME_KDF_MAX];
 	size_t last_kdf_count;
+	int error_code;
 };
 
 
@@ -99,6 +100,9 @@
 
 	data->eap_method = EAP_TYPE_AKA;
 
+	/* Zero is a valid error code, so we need to initialize */
+	data->error_code = NO_EAP_METHOD_ERROR;
+
 	eap_aka_state(data, CONTINUE);
 	data->prev_id = -1;
 
@@ -1025,8 +1029,17 @@
 	} else if (data->pseudonym) {
 		identity = data->pseudonym;
 		identity_len = data->pseudonym_len;
-	} else
-		identity = eap_get_config_identity(sm, &identity_len);
+	} else {
+		struct eap_peer_config *config;
+
+		config = eap_get_config(sm);
+		if (config && config->imsi_identity) {
+			identity = config->imsi_identity;
+			identity_len = config->imsi_identity_len;
+		} else {
+			identity = eap_get_config_identity(sm, &identity_len);
+		}
+	}
 	wpa_hexdump_ascii(MSG_DEBUG, "EAP-AKA: Selected identity for MK "
 			  "derivation", identity, identity_len);
 	if (data->eap_method == EAP_TYPE_AKA_PRIME) {
@@ -1171,6 +1184,7 @@
 
 	eap_sim_report_notification(sm->msg_ctx, attr->notification, 1);
 	if (attr->notification >= 0 && attr->notification < 32768) {
+		data->error_code = attr->notification;
 		eap_aka_state(data, FAILURE);
 	} else if (attr->notification == EAP_SIM_SUCCESS &&
 		   data->state == RESULT_SUCCESS)
@@ -1514,6 +1528,20 @@
 	return key;
 }
 
+static int eap_aka_get_error_code(void *priv)
+{
+	struct eap_aka_data *data = priv;
+
+	if (!data)
+		return NO_EAP_METHOD_ERROR;
+
+	int current_data_error = data->error_code;
+
+	/* Now reset for next transaction */
+	data->error_code = NO_EAP_METHOD_ERROR;
+
+	return current_data_error;
+}
 
 int eap_peer_aka_register(void)
 {
@@ -1535,6 +1563,7 @@
 	eap->init_for_reauth = eap_aka_init_for_reauth;
 	eap->get_identity = eap_aka_get_identity;
 	eap->get_emsk = eap_aka_get_emsk;
+	eap->get_error_code = eap_aka_get_error_code;
 
 	return eap_peer_method_register(eap);
 }
@@ -1562,6 +1591,7 @@
 	eap->init_for_reauth = eap_aka_init_for_reauth;
 	eap->get_identity = eap_aka_get_identity;
 	eap->get_emsk = eap_aka_get_emsk;
+	eap->get_error_code = eap_aka_get_error_code;
 
 	return eap_peer_method_register(eap);
 }
diff --git a/src/eap_peer/eap_config.h b/src/eap_peer/eap_config.h
index 16521c3..d416afd 100644
--- a/src/eap_peer/eap_config.h
+++ b/src/eap_peer/eap_config.h
@@ -46,6 +46,9 @@
 	 */
 	size_t anonymous_identity_len;
 
+	u8 *imsi_identity;
+	size_t imsi_identity_len;
+
 	/**
 	 * password - Password string for EAP
 	 *
diff --git a/src/eap_peer/eap_i.h b/src/eap_peer/eap_i.h
index 6ab2483..5b38969 100644
--- a/src/eap_peer/eap_i.h
+++ b/src/eap_peer/eap_i.h
@@ -14,6 +14,8 @@
 #include "eap_peer/eap.h"
 #include "eap_common/eap_common.h"
 
+#define NO_EAP_METHOD_ERROR (-1)
+
 /* RFC 4137 - EAP Peer state machine */
 
 typedef enum {
@@ -206,6 +208,17 @@
 	const u8 * (*get_identity)(struct eap_sm *sm, void *priv, size_t *len);
 
 	/**
+	 * get_error_code - Get latest EAP method error code
+	 * @priv: Pointer to private EAP method data from eap_method::init()
+	 * Returns: An int for the EAP Method Error code if exists or
+	 * NO_EAP_METHOD_ERROR otherwise
+	 *
+	 * This method is an optional handler that only EAP methods that need to
+	 * report their error code need to implement.
+	 */
+	int (*get_error_code)(void *priv);
+
+	/**
 	 * free - Free EAP method data
 	 * @method: Pointer to the method data registered with
 	 * eap_peer_method_register().
diff --git a/src/eap_peer/eap_proxy_qmi_oc.c b/src/eap_peer/eap_proxy_qmi_oc.c
new file mode 100644
index 0000000..4c07da5
--- /dev/null
+++ b/src/eap_peer/eap_proxy_qmi_oc.c
@@ -0,0 +1,2300 @@
+/*--------------------------------------------------------------------------
+Copyright (c) 2013, The Linux Foundation. All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+    * Redistributions of source code must retain the above copyright
+      notice, this list of conditions and the following disclaimer.
+    * Redistributions in binary form must reproduce the above
+      copyright notice, this list of conditions and the following
+      disclaimer in the documentation and/or other materials provided
+      with the distribution.
+    * Neither the name of The Linux Foundation nor the names of its
+      contributors may be used to endorse or promote products derived
+      from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+--------------------------------------------------------------------------*/
+
+#include "includes.h"
+#include "common.h"
+
+#ifdef CONFIG_EAP_PROXY
+#include "qmi_client.h"
+#include "eap_proxy_qmi.h"
+#include "qmi_client.h"
+#include "qmi_idl_lib.h"
+#include "authentication_service_v01.h"
+#include "user_identity_module_v01.h"
+#include "eap_config.h"
+#include "common/wpa_ctrl.h"
+#if defined(ANDROID)
+#include <cutils/properties.h>
+#ifdef CONFIG_EAP_PROXY_MDM_DETECT
+#include "mdm_detect.h"
+#endif /* CONFIG_EAP_PROXY_MDM_DETECT */
+#if defined(__BIONIC_FORTIFY)
+#include <sys/system_properties.h>
+#endif
+#endif
+#include <pthread.h>
+#include <sys/syscall.h>
+#include <sys/types.h>
+
+#define IMSI_LENGTH 15
+#define WPA_UIM_QMI_EVENT_MASK_CARD_STATUS        \
+                                        (1 << QMI_UIM_EVENT_CARD_STATUS_BIT_V01)
+#define WPA_UIM_QMI_EVENT_READ_TRANSPARENT_REQ    \
+                                        (1 << QMI_UIM_READ_TRANSPARENT_REQ_V01)
+
+/* Default timeout (in milli-seconds) for synchronous QMI message */
+#define WPA_UIM_QMI_DEFAULT_TIMEOUT               5000
+
+#define EAP_PROXY_PROPERTY_BASEBAND     "ro.baseband"
+#ifdef CONFIG_EAP_PROXY_MSM8994_TARGET
+#define EAP_PROXY_TARGET_PLATFORM       "ro.board.platform"
+#endif /* CONFIG_EAP_PROXY_MSM8994_TARGET */
+#if defined(__BIONIC_FORTIFY)
+#define EAP_PROXY_PROPERTY_BASEBAND_SIZE   PROP_VALUE_MAX
+#else
+#define EAP_PROXY_PROPERTY_BASEBAND_SIZE   10
+#endif
+#define EAP_PROXY_BASEBAND_VALUE_MSM       "msm"
+#define EAP_PROXY_BASEBAND_VALUE_APQ       "apq"
+#define EAP_PROXY_BASEBAND_VALUE_SVLTE1    "svlte1"
+#define EAP_PROXY_BASEBAND_VALUE_SVLTE2A   "svlte2a"
+#define EAP_PROXY_BASEBAND_VALUE_SGLTE     "sglte"
+#define EAP_PROXY_BASEBAND_VALUE_CSFB      "csfb"
+#define EAP_PROXY_BASEBAND_VALUE_MDMUSB    "mdm"
+#ifdef CONFIG_EAP_PROXY_MSM8994_TARGET
+#define EAP_PROXY_TARGET_PLATFORM_MSM8994  "msm8994"
+#endif /* CONFIG_EAP_PROXY_MSM8994_TARGET */
+#define EAP_PROXY_TARGET_FUSION4_5_PCIE    "fusion4_5_pcie"
+#define EAP_PROXY_BASEBAND_VALUE_UNDEFINED "undefined"
+
+#ifndef ANDROID
+#ifdef SYS_gettid
+static inline pid_t gettid(void)
+{
+        return syscall(SYS_gettid);
+}
+#else
+static inline pid_t gettid(void)
+{
+        return -1;
+}
+#endif
+#endif
+
+static Boolean wpa_qmi_ssr = FALSE;
+static void eap_proxy_qmi_deinit(struct eap_proxy_sm *eap_proxy);
+static void eap_proxy_eapol_sm_set_bool(struct eap_proxy_sm *sm,
+                         enum eapol_bool_var var, Boolean value);
+struct eap_proxy_sm *
+eap_proxy_init(void *eapol_ctx, const struct eapol_callbacks *eapol_cb,
+	       void *msg_ctx);
+static Boolean eap_proxy_eapol_sm_get_bool(struct eap_proxy_sm *sm,
+                                        enum eapol_bool_var var);
+
+/* Call-back function to process an authenticationr result indication from
+ * QMI EAP service */
+static void handle_qmi_eap_ind(qmi_client_type user_handle,
+                unsigned int msg_id,
+                void* ind_buf,
+                unsigned int ind_buf_len,
+                void* ind_cb_data);
+
+static u8 *eap_proxy_getKey(struct eap_proxy_sm *eap_proxy);
+static enum eap_proxy_status eap_proxy_qmi_response_wait(struct eap_proxy_sm *eap_proxy);
+static int eap_proxy_is_state_changed(struct eap_proxy_sm *sm);
+static enum eap_proxy_status eap_proxy_process(struct eap_proxy_sm  *eap_proxy,
+                                        u8 *eapReqData, int eapReqDataLen, struct eap_sm *eap_sm);
+static char bin_to_hexchar(u8 ch);
+
+static void wpa_qmi_client_indication_cb
+(
+        qmi_client_type                user_handle,
+        unsigned long                  msg_id,
+        unsigned char                 *ind_buf_ptr,
+        int                            ind_buf_len,
+        void                          *ind_cb_data
+);
+static void dump_buff(u8 *buff, int len);
+#ifdef CONFIG_CTRL_IFACE
+static const char *eap_proxy_sm_state_txt(int state);
+#endif /* CONFIG_CTRL_IFACE */
+static Boolean eap_proxy_build_identity(struct eap_proxy_sm *eap_proxy, u8 id,
+                                                 struct eap_sm *eap_sm);
+
+#ifdef SIM_AKA_IDENTITY_IMSI
+static char *imsi;
+static int imsi_len_g = 0;
+static int card_mnc_len = -1;
+#ifdef CONFIG_EAP_PROXY_DUAL_SIM
+static unsigned int slot = 0;
+static unsigned int session_type;
+#endif /* CONFIG_EAP_PROXY_DUAL_SIM */
+
+static Boolean wpa_qmi_register_events(int sim_num, wpa_uim_struct_type *wpa_uim);
+static Boolean wpa_qmi_read_card_imsi(int sim_num, wpa_uim_struct_type *wpa_uim);
+static Boolean wpa_qmi_read_card_status(int sim_num, wpa_uim_struct_type *wpa_uim);
+static Boolean wpa_qmi_register_auth_inds(struct eap_proxy_sm *eap_proxy);
+
+#endif
+#define EAP_SUB_TYPE_SIM_START     0x0a
+#define EAP_SUB_TYPE_AKA_IDENTITY  0x05
+#define EAP_RESP_TYPE_NAK             3
+
+
+#ifdef SIM_AKA_IDENTITY_IMSI
+static void wpa_qmi_client_indication_cb
+(
+        qmi_client_type                user_handle,
+        unsigned long                  msg_id,
+        unsigned char                 *ind_buf_ptr,
+        int                            ind_buf_len,
+        void                          *ind_cb_data
+)
+{
+	u32 decoded_payload_len = 0;
+	qmi_client_error_type qmi_err = QMI_NO_ERR;
+	void * decoded_payload = NULL;
+	struct eap_proxy_sm *eap_proxy = ind_cb_data;
+	uim_status_change_ind_msg_v01* status_change_ind_ptr = NULL;
+	struct wpa_supplicant *wpa_s = NULL;
+	u32 i, card_info_len = 0;
+
+	wpa_printf(MSG_DEBUG, "eap_proxy: %s: msg_id=0x%lx", __func__, msg_id);
+
+	if (user_handle == NULL) {
+		wpa_printf(MSG_ERROR, "eap_proxy: qmi_client_type missing in callback");
+		return;
+	}
+
+	if (eap_proxy == NULL) {
+		wpa_printf(MSG_ERROR, "eap_proxy: not initialized, discard client indiataion");
+		return;
+	}
+
+	if (ind_buf_ptr == NULL) {
+		wpa_printf(MSG_ERROR, "eap_proxy: indication buffer NULL, discard client indiataion");
+		return;
+	}
+
+	qmi_idl_get_message_c_struct_len(uim_get_service_object_v01(),
+					 QMI_IDL_INDICATION, msg_id,
+					 &decoded_payload_len);
+
+	if(!decoded_payload_len) {
+		wpa_printf(MSG_ERROR, "eap_proxy: cann't decode payload, discard client indiataion");
+		return;
+	}
+
+	decoded_payload = os_zalloc(decoded_payload_len);
+	if (decoded_payload == NULL) {
+		wpa_printf(MSG_ERROR, "eap_proxy: failed to allocate memory");
+		return;
+	}
+
+	qmi_err = qmi_client_message_decode(user_handle,
+					    QMI_IDL_INDICATION, msg_id,
+					    ind_buf_ptr, ind_buf_len,
+					    decoded_payload, decoded_payload_len);
+
+	if (qmi_err == QMI_NO_ERR) {
+		switch (msg_id) {
+		case QMI_UIM_STATUS_CHANGE_IND_V01:
+			status_change_ind_ptr = (uim_status_change_ind_msg_v01*)decoded_payload;
+			if (!status_change_ind_ptr->card_status_valid)
+				goto fail;
+
+			card_info_len = status_change_ind_ptr->card_status.card_info_len;
+			for (i = 0; i < card_info_len; i++) {
+				if(UIM_CARD_STATE_PRESENT_V01 !=
+				    status_change_ind_ptr->card_status.card_info[i].card_state) {
+					wpa_printf(MSG_DEBUG, "eap_proxy: %s SIM card removed. flush pmksa entries.", __func__);
+					eap_proxy->eapol_cb->eap_proxy_notify_sim_status(eap_proxy->ctx, SIM_STATE_ERROR);
+					break; /* only one flush will do */
+				}
+			}
+			break;
+		default:
+			wpa_printf(MSG_DEBUG, "eap_proxy: Unknown QMI Indicaiton %lu", msg_id);
+			break;
+		}
+	}
+fail:
+	os_free(decoded_payload);
+	return;
+}
+
+static Boolean wpa_qmi_register_auth_inds(struct eap_proxy_sm *eap_proxy)
+{
+        qmi_client_error_type               qmi_err_code      = 0;
+        auth_indication_register_resp_msg_v01  event_resp_msg;
+        auth_indication_register_req_msg_v01 event_reg_params;
+
+        /* Register for events first */
+        os_memset(&event_reg_params, 0, sizeof(auth_indication_register_req_msg_v01));
+        os_memset(&event_resp_msg, 0, sizeof(auth_indication_register_resp_msg_v01));
+
+        event_reg_params.report_eap_notification_code_valid = TRUE;
+        event_reg_params.report_eap_notification_code = 1;
+
+        wpa_printf(MSG_DEBUG, "registering for notification codes\n");
+        qmi_err_code = qmi_client_send_msg_sync(
+                        eap_proxy->qmi_auth_svc_client_ptr[eap_proxy->user_selected_sim],
+                        QMI_AUTH_INDICATION_REGISTER_REQ_V01,
+                        (void *) &event_reg_params,
+                        sizeof(auth_indication_register_req_msg_v01),
+                        (void*) &event_resp_msg,
+                        sizeof(auth_indication_register_resp_msg_v01),
+                        WPA_UIM_QMI_DEFAULT_TIMEOUT);
+
+        if (qmi_err_code != QMI_NO_ERR ||
+            (event_resp_msg.resp.result != QMI_RESULT_SUCCESS_V01 &&
+             event_resp_msg.resp.error != QMI_ERR_NO_EFFECT_V01)) {
+                wpa_printf(MSG_ERROR,"QMI-ERROR Error for "
+                           "QMI_AUTH_INDICATION_REGISTER_REQ_V01, qmi_err_code=%d"
+                           "Error=%d\n", qmi_err_code,
+                            event_resp_msg.resp.error);
+                return FALSE;
+        }
+
+        return TRUE;
+
+}
+
+static Boolean wpa_qmi_register_events(int sim_num, wpa_uim_struct_type *wpa_uim)
+{
+        qmi_client_error_type               qmi_err_code      = 0;
+        uim_event_reg_resp_msg_v01          event_resp_msg;
+        uim_event_reg_req_msg_v01           event_reg_params;
+
+        /* Register for events first */
+        os_memset(&event_reg_params, 0, sizeof(uim_event_reg_req_msg_v01));
+        os_memset(&event_resp_msg, 0, sizeof(uim_event_reg_resp_msg_v01));
+
+        event_reg_params.event_mask |= (WPA_UIM_QMI_EVENT_MASK_CARD_STATUS);
+        qmi_err_code = qmi_client_send_msg_sync(wpa_uim[sim_num].qmi_uim_svc_client_ptr,
+                                                QMI_UIM_EVENT_REG_REQ_V01,
+                                                (void *) &event_reg_params,
+                                                sizeof(uim_event_reg_req_msg_v01),
+                                                (void *) &event_resp_msg,
+                                                sizeof(uim_event_reg_resp_msg_v01),
+                                                WPA_UIM_QMI_DEFAULT_TIMEOUT);
+
+        wpa_printf(MSG_ERROR, "eap_proxy: QMI_UIM_EVENT_REG_REQ_V01, "
+                   "qmi_err_code: 0x%x wpa_uim[%d].qmi_uim_svc_client_ptr =%p"
+                   "Error=0x%x", qmi_err_code, sim_num,
+                    wpa_uim[sim_num].qmi_uim_svc_client_ptr,
+                    event_resp_msg.resp.error);
+
+        if (qmi_err_code != QMI_NO_ERR ||
+            (event_resp_msg.resp.result != QMI_RESULT_SUCCESS_V01 &&
+             event_resp_msg.resp.error != QMI_ERR_NO_EFFECT_V01)) {
+                wpa_printf(MSG_ERROR,"QMI-ERROR Error for "
+                           "QMI_UIM_EVENT_REG_REQ_V01, qmi_err_code=%d"
+                           "Error=%d\n", qmi_err_code,
+                            event_resp_msg.resp.error);
+                return FALSE;
+        }
+
+        if(event_resp_msg.event_mask_valid)
+        {
+                wpa_printf(MSG_ERROR, "eap_proxy: event_resp_msg.event=%d,\n",
+                           event_resp_msg.event_mask);
+
+        }
+
+        if (wpa_qmi_read_card_status(sim_num, wpa_uim))
+                return TRUE;
+        else {
+                wpa_printf(MSG_ERROR,"eap_proxy: Error while reading SIM card status\n");
+                return FALSE;
+        }
+}
+
+static Boolean wpa_qmi_read_card_status(int sim_num, wpa_uim_struct_type *wpa_uim)
+{
+        unsigned int                        i = 0, j = 0;
+        Boolean                             card_found = FALSE;
+        qmi_client_error_type               qmi_err_code      = 0;
+        uim_get_card_status_resp_msg_v01   card_status_resp_msg;
+
+        wpa_printf (MSG_ERROR, "eap_proxy: reading card %d values\n", sim_num+1);
+        os_memset(&card_status_resp_msg,
+                  0,
+                  sizeof(uim_get_card_status_resp_msg_v01));
+        qmi_err_code = qmi_client_send_msg_sync(wpa_uim[sim_num].qmi_uim_svc_client_ptr,
+                                                QMI_UIM_GET_CARD_STATUS_REQ_V01,
+                                                NULL,
+                                                0,
+                                                (void *)&card_status_resp_msg,
+                                                sizeof(uim_get_card_status_resp_msg_v01),
+                                                WPA_UIM_QMI_DEFAULT_TIMEOUT);
+
+        if (qmi_err_code != QMI_NO_ERR ||
+            card_status_resp_msg.resp.result != QMI_RESULT_SUCCESS_V01) {
+                wpa_printf(MSG_ERROR, "QMI-ERROR Error for "
+                           "QMI_UIM_GET_CARD_STATUS_REQ_V01, qmi_err_code: 0x%x\n "
+                           "resp_err = %d \n", qmi_err_code, card_status_resp_msg.resp.error);
+                return FALSE;
+        }
+
+        /* Updated global card status if needed */
+        if (!card_status_resp_msg.card_status_valid ||
+            (card_status_resp_msg.resp.result != QMI_RESULT_SUCCESS_V01)) {
+                wpa_printf(MSG_ERROR, "eap_proxy: card_status is not valid !\n");
+                return FALSE;
+        }
+        /* Update global in case of new card state or error code */
+        i = sim_num;
+        if ( i < QMI_UIM_CARDS_MAX_V01 &&
+             i < card_status_resp_msg.card_status.card_info_len ) {
+                wpa_printf(MSG_ERROR, "eap_proxy: card_info[i].card_state: 0x%x\n",
+                        card_status_resp_msg.card_status.card_info[i].card_state);
+                wpa_printf(MSG_ERROR, "eap_proxy: card_info[i].error_code: 0x%x\n",
+                        card_status_resp_msg.card_status.card_info[i].error_code);
+
+                wpa_uim[sim_num].card_info[i].card_state =
+                        card_status_resp_msg.card_status.card_info[i].card_state;
+
+                wpa_uim[sim_num].card_info[i].card_error_code =
+                        card_status_resp_msg.card_status.card_info[i].error_code;
+#ifdef CONFIG_EAP_PROXY_DUAL_SIM
+            do {
+                   if (card_status_resp_msg.card_status.index_gw_pri != 0xFFFF) {
+                        slot = (card_status_resp_msg.card_status.index_gw_pri & 0xFF00) >> 8;
+                        if (slot == i) {
+                            session_type = UIM_SESSION_TYPE_PRIMARY_GW_V01;
+                            wpa_printf (MSG_ERROR, "eap_proxy: read_card_status:"
+                                        " prime slot = %d\n", slot);
+                            break;
+                        }
+                   }
+                   if (card_status_resp_msg.card_status.index_gw_sec != 0xFFFF) {
+                        slot = (card_status_resp_msg.card_status.index_gw_sec & 0xFF00) >> 8;
+                        if (slot == i) {
+                            session_type = UIM_SESSION_TYPE_SECONDARY_GW_V01;
+                            wpa_printf (MSG_ERROR, "eap_proxy: read_card_status: "
+                                        "second slot = %d\n", slot);
+                            break;
+                        }
+                   }
+                   wpa_printf (MSG_ERROR, "eap_proxy: read_card_status: Not GW it's 1x\n");
+                   return FALSE;
+                }while(0);
+
+                if (slot > 1){
+                            wpa_printf (MSG_ERROR, "eap_proxy: read_card_status: "
+                                        "INVALID slot = %d and i = %d\n", slot, i);
+                        return FALSE;
+                }
+#endif /* CONFIG_EAP_PROXY_DUAL_SIM */
+
+                if (card_status_resp_msg.card_status.card_info[i].card_state ==
+                    UIM_CARD_STATE_PRESENT_V01) {
+                        for (j = 0 ; j < QMI_UIM_APPS_MAX_V01 ; j++) {
+                                wpa_uim[sim_num].card_info[i].app_type = card_status_resp_msg.
+                                        card_status.card_info[i].app_info[j].app_type;
+
+                                wpa_uim[sim_num].card_info[i].app_state = card_status_resp_msg.
+                                        card_status.card_info[i].app_info[j].app_state;
+
+                                if (((card_status_resp_msg.card_status.card_info[i].
+                                     app_info[j].app_type == 1) || (card_status_resp_msg.
+                                     card_status.card_info[i].app_info[j].app_type == 2)) &&
+                                    (card_status_resp_msg.card_status.card_info[i].app_info[j].
+                                     app_state == UIM_APP_STATE_READY_V01)) {
+                                        wpa_printf(MSG_ERROR, "eap_proxy: card READY\n");
+                                        wpa_printf(MSG_ERROR, "eap_proxy: card_info[i].app_ty"
+                                                "pe: 0x%x\n", card_status_resp_msg.card_status.
+                                                card_info[i].app_info[j].app_type);
+                                        wpa_printf(MSG_ERROR, "eap_proxy: card_info[i].app_sta"
+                                                "te : 0x%x\n", card_status_resp_msg.card_status
+                                                .card_info[i].app_info[j].app_state);
+                                        card_found = TRUE;
+                                        break;
+                                }
+                        }
+                }
+
+                if (card_found) {
+                        wpa_printf(MSG_ERROR, "eap_proxy: card found for SIM = %d\n", sim_num+1);
+                }
+        }
+
+        if ((!card_found) || (i == QMI_UIM_CARDS_MAX_V01) ||
+                (j == QMI_UIM_APPS_MAX_V01)) {
+                wpa_printf(MSG_ERROR, "eap_proxy: SIM/USIM not ready card_found=%d\n",card_found);
+                return FALSE;
+        }
+
+        wpa_printf(MSG_ERROR, "eap_proxy: SIM/USIM ready\n");
+        wpa_uim[sim_num].card_ready_idx = i;
+
+        return TRUE;
+} /* wpa_qmi_read_card_status */
+
+static int check_for_3_digit()
+{
+        int mcc = 0,i =0;
+        /*
+        -- 3 digits if MCC belongs to this group: 302, 310, 311, 312, 313, 314, 315,
+        316, 334, 348 (decimal)
+        -- 2 digits in all other cases
+        Note: imsi values are hex characters
+        */
+        int valid_mcc[] = {302, 310, 311, 312, 313, 314, 315, 316, 334, 348};
+
+        mcc = ((imsi[0]-0x30)*100) + ((imsi[1]-0x30)*10) + (imsi[2]-0x30);
+
+        wpa_printf(MSG_ERROR, "mcc from the SIM is %d\n", mcc);
+        for(i = 0; i < sizeof(valid_mcc)/sizeof(valid_mcc[0]); i++)
+        {
+                if(mcc == valid_mcc[i])
+                        return 1;
+        }
+        return 0;
+}
+
+static Boolean wpa_qmi_read_card_imsi(int sim_num, wpa_uim_struct_type *wpa_uim)
+{
+        int                     length;
+        unsigned char           *data;
+        int                     src = 0, dst = 0;
+        Boolean                 card_found = FALSE,
+        qmi_status = TRUE;
+        qmi_client_error_type               qmi_err_code = 0;
+        uim_read_transparent_req_msg_v01   qmi_read_trans_req;
+        uim_read_transparent_resp_msg_v01  read_trans_resp;
+        card_mnc_len = -1;
+
+
+        os_memset(&read_trans_resp, 0,
+                  sizeof(uim_read_transparent_resp_msg_v01));
+        os_memset(&qmi_read_trans_req, 0,
+                        sizeof(uim_read_transparent_req_msg_v01));
+
+        qmi_read_trans_req.read_transparent.length = 0;
+        qmi_read_trans_req.read_transparent.offset = 0;
+        qmi_read_trans_req.file_id.file_id = 0x6F07;
+        qmi_read_trans_req.file_id.path_len = 4;
+
+#ifdef CONFIG_EAP_PROXY_DUAL_SIM
+        wpa_printf (MSG_ERROR, "eap_proxy: read_card_imsi: session_type = %d\n", session_type);
+        qmi_read_trans_req.session_information.session_type = session_type;
+#else
+        qmi_read_trans_req.session_information.session_type =
+                                UIM_SESSION_TYPE_PRIMARY_GW_V01;
+#endif /* CONFIG_EAP_PROXY_DUAL_SIM */
+        qmi_read_trans_req.session_information.aid_len = 0;
+
+        /* For USIM*/
+        if ((wpa_uim[sim_num].card_info[wpa_uim[sim_num].card_ready_idx].app_type ==
+                UIM_APP_TYPE_USIM_V01)) {
+                qmi_read_trans_req.file_id.path[0] = 0x00;
+                qmi_read_trans_req.file_id.path[1] = 0x3F;
+                qmi_read_trans_req.file_id.path[2] = 0xFF;
+                qmi_read_trans_req.file_id.path[3] = 0x7F;
+
+        } else /* For SIM*/
+        if ((wpa_uim[sim_num].card_info[wpa_uim[sim_num].card_ready_idx].app_type ==
+                UIM_APP_TYPE_SIM_V01)) {
+                qmi_read_trans_req.file_id.path[0] = 0x00;
+                qmi_read_trans_req.file_id.path[1] = 0x3F;
+                qmi_read_trans_req.file_id.path[2] = 0x20;
+                qmi_read_trans_req.file_id.path[3] = 0x7F;
+        }
+        else {
+                return FALSE;
+        }
+
+        qmi_err_code = qmi_client_send_msg_sync(wpa_uim[sim_num].qmi_uim_svc_client_ptr,
+                                        QMI_UIM_READ_TRANSPARENT_REQ_V01,
+                                        (void *)&qmi_read_trans_req,
+                                        sizeof(uim_read_transparent_req_msg_v01),
+                                        (void *) &read_trans_resp,
+                                        sizeof(uim_read_transparent_resp_msg_v01),
+                                        WPA_UIM_QMI_DEFAULT_TIMEOUT);
+        if (QMI_NO_ERR != qmi_err_code ||
+            read_trans_resp.resp.result != QMI_RESULT_SUCCESS_V01) {
+                wpa_printf(MSG_ERROR, "QMI-ERROR Unable to read IMSI from UIM service;"
+                           " error_ret=%d; qmi_err=%d\n", qmi_err_code,
+                           read_trans_resp.resp.error);
+                qmi_status = FALSE;
+        }
+
+        if (QMI_NO_ERR == qmi_err_code) {
+                if (read_trans_resp.read_result_valid) {
+                        length  =
+                                read_trans_resp.read_result.content_len;
+                        data    =
+                                read_trans_resp.read_result.content;
+                                wpa_printf(MSG_ERROR,
+                                        "eap_proxy: IMSI SIM content length = %d\n",
+                                        length);
+
+                        /* Received IMSI is in the 3GPP format
+                                converting it into ascii string */
+                        imsi = os_zalloc(2 * length);
+                        if (imsi == NULL) {
+                                wpa_printf(MSG_ERROR,
+                                        "eap_proxy: Couldn't allocate memmory for imsi");
+                                return FALSE;
+                        }
+                        for (src = 1, dst = 0;
+                                (src < length) && (dst < (length * 2));
+                                src++) {
+                                wpa_printf(MSG_ERROR,
+                                        "eap_proxy: IMSI read from SIM = %d src %d\n",
+                                        data[src], src);
+                                if(data[src] == 0xFF) {
+                                        break;
+                                }
+                                if (src > 1) {
+                                        imsi[dst] = bin_to_hexchar(data[src] & 0x0F);
+                                        dst++;
+                                        wpa_printf(MSG_ERROR,
+                                        "eap_proxy: IMSI dst = %d dst %d\n",
+                                        imsi[dst-1], dst);
+                                }
+                                /* Process upper part of byte for all bytes */
+                                imsi[dst] = bin_to_hexchar(data[src] >> 4);
+                                dst++;
+                                wpa_printf(MSG_ERROR,
+                                        "eap_proxy: IMSI dst = %d dst %d\n",
+                                        imsi[dst-1], dst);
+                        }
+                                imsi_len_g = (data[0]*2 - 1); //dst;
+                                wpa_printf(MSG_ERROR,
+                                        "eap_proxy: IMSI first digit = %d read length = %d"
+                                        "imsi %20s\n", data[0],imsi_len_g, imsi);
+                        } else{
+                                wpa_printf(MSG_ERROR,
+                                        "eap_proxy: IMSI read failure read_result_valid = %d\n",
+                                        read_trans_resp.read_result_valid);
+                                qmi_status = FALSE;
+                        }
+                }
+        /* READ EF_AD */
+        /* if qmi_status is FALSE, UIM read for mnc may not be required - To Do */
+        qmi_read_trans_req.file_id.file_id = 0x6FAD;
+        qmi_err_code = qmi_client_send_msg_sync(wpa_uim[sim_num].qmi_uim_svc_client_ptr,
+                                        QMI_UIM_READ_TRANSPARENT_REQ_V01,
+                                        (void *)&qmi_read_trans_req,
+                                        sizeof(uim_read_transparent_req_msg_v01),
+                                        (void *)&read_trans_resp,
+                                        sizeof(uim_read_transparent_resp_msg_v01),
+                                        WPA_UIM_QMI_DEFAULT_TIMEOUT);
+        if (QMI_NO_ERR != qmi_err_code ||
+           read_trans_resp.resp.result != QMI_RESULT_SUCCESS_V01) {
+                wpa_printf(MSG_ERROR, "QMI-ERROR Unable to read MNC from UIM service;"
+                           " error_ret=%d; qmi_err=%d\n", qmi_err_code,
+                           read_trans_resp.resp.error);
+                qmi_status = FALSE;
+        }
+        if (QMI_NO_ERR == qmi_err_code) {
+                if (read_trans_resp.read_result_valid) {
+                        length  =
+                                read_trans_resp.read_result.content_len;
+                        data    =
+                                read_trans_resp.read_result.content;
+
+                        if(length >= 4)
+                                card_mnc_len = 0x0f & data[3];
+                        if ((card_mnc_len != 2) && (card_mnc_len != 3)) {
+                                if(check_for_3_digit())
+                                        card_mnc_len = 3;
+                                else
+                                        card_mnc_len = 2;
+                                wpa_printf(MSG_ERROR, "Failed to get MNC length from (U)SIM "
+                                "assuming %d as mcc %s to 3 digit mnc group\n",
+                                card_mnc_len, card_mnc_len == 3? "belongs":"not belongs");
+                        }
+                }
+        }
+
+
+        return qmi_status;
+} /* wpa_qmi_read_card_imsi */
+#endif /* SIM_AKA_IDENTITY_IMSI */
+
+#ifdef CONFIG_EAP_PROXY_MDM_DETECT
+static int eap_modem_compatible(struct dev_info *mdm_detect_info)
+{
+        char args[EAP_PROXY_PROPERTY_BASEBAND_SIZE] = {0};
+        int ret = 0;
+
+        /* Get the hardware property */
+        ret = property_get(EAP_PROXY_PROPERTY_BASEBAND, args, "");
+        if (ret > EAP_PROXY_PROPERTY_BASEBAND_SIZE){
+                wpa_printf(MSG_ERROR,"eap_proxy: property [%s] has size [%d] that exceeds max [%d]",
+                           EAP_PROXY_PROPERTY_BASEBAND,
+                           ret,
+                           EAP_PROXY_PROPERTY_BASEBAND_SIZE);
+                return FALSE;
+        }
+
+        /* This will check for the type of hardware, and if the hardware type
+         * needs external modem, it will check if the modem type is external */
+        if(!os_strncmp(EAP_PROXY_BASEBAND_VALUE_APQ, args, 3)) {
+                for (ret = 0; ret < mdm_detect_info->num_modems; ret++) {
+                        if (mdm_detect_info->mdm_list[ret].type == MDM_TYPE_EXTERNAL) {
+                                wpa_printf(MSG_INFO, "eap_proxy: hardware supports external modem");
+                                return TRUE;
+                        }
+                }
+                wpa_printf(MSG_ERROR, "eap_proxy: hardware does not support external modem");
+                return FALSE;
+        }
+        return TRUE;
+}
+#endif /* CONFIG_EAP_PROXY_MDM_DETECT */
+
+void wpa_qmi_register_notification(void *eloop_ctx, void *timeout_ctx)
+{
+        struct eap_proxy_sm *eap_proxy = eloop_ctx;
+        wpa_printf(MSG_DEBUG, "eap_proxy: %s", __func__);
+
+        eap_proxy_qmi_deinit(eap_proxy);
+        eap_proxy_init(eap_proxy, NULL, NULL);
+}
+
+void wpa_qmi_handle_ssr(qmi_client_type user_handle, qmi_client_error_type error, void *err_cb_data)
+{
+        struct eap_proxy_sm *eap_proxy = err_cb_data;
+
+        wpa_printf(MSG_DEBUG, "eap_proxy: %s ", __func__);
+
+        wpa_qmi_ssr = TRUE;
+        eloop_register_timeout(0, 0, wpa_qmi_register_notification, eap_proxy, NULL);
+}
+
+
+static void exit_proxy_init(int signum)
+{
+       pthread_exit(NULL);
+}
+
+static void eap_proxy_post_init(struct eap_proxy_sm *eap_proxy)
+{
+        int qmiErrorCode;
+        int qmiRetCode;
+        qmi_idl_service_object_type qmi_client_service_obj[MAX_NO_OF_SIM_SUPPORTED];
+        int index;
+        static Boolean flag = FALSE;
+        struct sigaction    actions;
+        int ret = 0;
+        wpa_uim_struct_type *wpa_uim = eap_proxy->wpa_uim;
+#ifdef CONFIG_EAP_PROXY_MDM_DETECT
+        struct dev_info mdm_detect_info;
+
+        /* Call ESOC API to get the number of modems.
+         * If the number of modems is not zero, only then proceed
+         * with the eap_proxy intialization.
+         */
+        ret = get_system_info(&mdm_detect_info);
+        if (ret > 0)
+                wpa_printf(MSG_ERROR, "eap_proxy: Failed to get system info, ret %d", ret);
+
+        if (mdm_detect_info.num_modems == 0) {
+                eap_proxy->proxy_state = EAP_PROXY_DISABLED;
+                wpa_printf(MSG_ERROR, "eap_proxy: No Modem support for this target"
+                           " number of modems is %d", mdm_detect_info.num_modems);
+                return;
+        }
+        wpa_printf(MSG_DEBUG, "eap_proxy: num_modems = %d", mdm_detect_info.num_modems);
+
+        if(eap_modem_compatible(&mdm_detect_info) == FALSE) {
+                eap_proxy->proxy_state = EAP_PROXY_DISABLED;
+                wpa_printf(MSG_ERROR, "eap_proxy: build does not support EAP-SIM feature");
+                return;
+        }
+#endif /* CONFIG_EAP_PROXY_MDM_DETECT */
+
+        sigemptyset(&actions.sa_mask);
+        actions.sa_flags = 0;
+        actions.sa_handler = exit_proxy_init;
+        ret = sigaction(SIGUSR1,&actions,NULL);
+        if(ret < 0)
+                wpa_printf(MSG_DEBUG, "sigaction\n");
+        eap_proxy->proxy_state = EAP_PROXY_INITIALIZE;
+        eap_proxy->qmi_state = QMI_STATE_IDLE;
+        eap_proxy->key = NULL;
+        eap_proxy->iskey_valid = FALSE;
+        eap_proxy->is_state_changed = FALSE;
+        eap_proxy->isEap = FALSE;
+        eap_proxy->eap_type = EAP_TYPE_NONE;
+        eap_proxy->user_selected_sim = 0;
+
+#ifdef CONFIG_EAP_PROXY_DUAL_SIM
+        wpa_printf (MSG_ERROR,
+                "eap_proxy: eap_proxy Initializing for DUAL SIM build %d tid %d",
+                MAX_NO_OF_SIM_SUPPORTED, gettid());
+#else
+        wpa_printf (MSG_ERROR,
+                "eap_proxy: eap_proxy Initializing for Single SIM build %d tid %d",
+                MAX_NO_OF_SIM_SUPPORTED, gettid());
+#endif
+
+
+        for (index = 0; index < MAX_NO_OF_SIM_SUPPORTED; ++index) {
+
+#ifdef SIM_AKA_IDENTITY_IMSI
+                if (FALSE == eap_proxy->qmi_uim_svc_client_initialized[index])  {
+                        qmi_client_os_params eap_os_params;
+                        /* Init QMI_UIM service for EAP-SIM/AKA */
+                        os_memset(&eap_os_params, 0, sizeof(qmi_client_os_params));
+
+                        qmiErrorCode = qmi_client_init_instance(
+                                        uim_get_service_object_v01(),
+                                        QMI_CLIENT_INSTANCE_ANY,
+                                        wpa_qmi_client_indication_cb,
+                                        eap_proxy, &eap_os_params,
+                                        10000,
+                                        &wpa_uim[index].qmi_uim_svc_client_ptr);
+
+                        if ((wpa_uim[index].qmi_uim_svc_client_ptr == NULL) || (qmiErrorCode > 0)) {
+                                wpa_printf(MSG_ERROR, "eap_proxy: Could not register with QMI UIM"
+                                        "Service, qmi_uim_svc_client_ptr: %p,qmi_err_code: %d\n",
+                                        wpa_uim[index].qmi_uim_svc_client_ptr, qmiErrorCode);
+                                wpa_uim[index].qmi_uim_svc_client_ptr = NULL;
+                                flag = FALSE;
+                                continue;
+                        }
+                        eap_proxy->qmi_uim_svc_client_initialized[index] = TRUE;
+
+                        wpa_printf (MSG_ERROR, "eap_proxy: QMI uim service client initialized with"
+                                "success tid is %d %p %d\n",
+                                gettid(), wpa_uim[index].qmi_uim_svc_client_ptr, qmiErrorCode);
+                        /* Register the card events with the QMI / UIM */
+                        wpa_qmi_register_events(index, wpa_uim);
+                        qmiErrorCode = qmi_client_register_error_cb(
+                                wpa_uim[index].qmi_uim_svc_client_ptr, wpa_qmi_handle_ssr, eap_proxy);
+                        wpa_printf(MSG_DEBUG,
+                                "eap_proxy: qmi_client_register_error_cb() status %d\n", qmiErrorCode);
+                        wpa_qmi_ssr = FALSE;
+                } else
+                        wpa_printf (MSG_ERROR, "eap_proxy: QMI uim service client is already init"
+                                "ialized tid is %d \n", gettid());
+
+
+                qmi_client_os_params eap_os_params;
+                os_memset(&eap_os_params, 0, sizeof(qmi_client_os_params));
+
+                qmiErrorCode = qmi_client_init_instance(auth_get_service_object_v01(),
+                                                        QMI_CLIENT_INSTANCE_ANY,
+                                                        handle_qmi_eap_ind,
+                                                        eap_proxy,
+                                                        &eap_os_params,
+                                                        10000,
+                                                        &eap_proxy->qmi_auth_svc_client_ptr[index]);
+
+
+                if ((eap_proxy->qmi_auth_svc_client_ptr[index] == NULL) || (qmiErrorCode > 0)) {
+                        wpa_printf(MSG_ERROR, "eap_proxy: Could not register with QMI auth Service "
+                                        "qmi_auth_svc_client_ptr: %p,qmi_err_code: %d\n",
+                                        eap_proxy->qmi_auth_svc_client_ptr[index], qmiErrorCode);
+                        eap_proxy->qmi_auth_svc_client_ptr[index] = NULL;
+                        flag = FALSE;
+                        continue;
+                }
+                wpa_printf (MSG_ERROR, "eap_proxy: QMI auth service client initialized with success"
+                        " tid is %d  %p eapol_proxy=%p\n", gettid(),
+                                eap_proxy->qmi_auth_svc_client_ptr[index], eap_proxy);
+                flag = TRUE;
+                /* Register for the notifications from QMI / AUTH */
+                wpa_qmi_register_auth_inds(eap_proxy);
+#endif /* SIM_AKA_IDENTITY_IMSI */
+        }
+
+        if ( flag == FALSE ) {
+                eap_proxy->proxy_state = EAP_PROXY_DISABLED;
+                wpa_printf(MSG_ERROR, "eap_proxy: flag = %d proxy init failed\n", flag);
+                return;
+        }
+
+        eap_proxy->proxy_state = EAP_PROXY_IDLE;
+        eap_proxy_eapol_sm_set_bool(eap_proxy, EAPOL_eapSuccess, FALSE);
+        eap_proxy_eapol_sm_set_bool(eap_proxy, EAPOL_eapFail, FALSE);
+        eap_proxy_eapol_sm_set_bool(eap_proxy, EAPOL_eapRestart, FALSE);
+        eap_proxy_eapol_sm_set_bool(eap_proxy, EAPOL_eapResp, FALSE);
+        eap_proxy_eapol_sm_set_bool(eap_proxy, EAPOL_eapNoResp, FALSE);
+        wpa_printf (MSG_ERROR, "eap_proxy: Eap_proxy initialized successfully"
+                " tid is %d \n", gettid());
+        return;
+
+}
+
+int eap_auth_end_eap_session(qmi_client_type qmi_auth_svc_client_ptr)
+{
+        qmi_client_error_type qmiRetCode = 0;
+        auth_end_eap_session_resp_msg_v01 end_eap_session_resp_msg ;
+
+        wpa_printf(MSG_ERROR, "eap_proxy: eap_auth_end_eap_session: Ending EAP auth session");
+
+
+        /* Send QMI_AUTH_END_EAP_SESSION_REQ */
+
+        os_memset(&end_eap_session_resp_msg,
+                        0,
+                        sizeof(auth_end_eap_session_resp_msg_v01));
+
+        qmiRetCode = qmi_client_send_msg_sync(qmi_auth_svc_client_ptr,
+                                              QMI_AUTH_END_EAP_SESSION_REQ_V01,
+                                              NULL,
+                                              0,
+                                              (void *) &end_eap_session_resp_msg,
+                                              sizeof(auth_end_eap_session_resp_msg_v01),
+                                              WPA_UIM_QMI_DEFAULT_TIMEOUT);
+
+        if (QMI_NO_ERR != qmiRetCode ||
+            end_eap_session_resp_msg.resp.result != QMI_RESULT_SUCCESS_V01) {
+                wpa_printf(MSG_ERROR, "QMI-ERROR Unable to End the EAP session;"
+                                " error_ret=%d; qmi_err=%d\n", qmiRetCode,
+                                end_eap_session_resp_msg.resp.error);
+                return -1;
+        }
+
+        wpa_printf(MSG_ERROR, "eap_proxy: eap_auth_end_eap_session:"
+                " EAP auth session ended successfuly");
+
+        return 0;
+}
+
+static void eap_proxy_schedule_thread(void *eloop_ctx, void *timeout_ctx)
+{
+        struct eap_proxy_sm *eap_proxy = eloop_ctx;
+        pthread_attr_t attr;
+        int ret = -1;
+
+        pthread_attr_init(&attr);
+        pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
+        ret = pthread_create(&eap_proxy->thread_id, &attr, eap_proxy_post_init, eap_proxy);
+        if(ret < 0)
+               wpa_printf(MSG_ERROR, "eap_proxy: starting thread is failed %d\n", ret);
+}
+
+struct eap_proxy_sm *
+eap_proxy_init(void *eapol_ctx, const struct eapol_callbacks *eapol_cb,
+               void *msg_ctx)
+{
+        int qmiErrorCode;
+        int qmiRetCode;
+        struct eap_proxy_sm *eap_proxy;
+        qmi_idl_service_object_type    qmi_client_service_obj;
+
+        wpa_printf(MSG_DEBUG, "eap_proxy: %s  "
+                 "wpa_qmi_ssr %d", __func__, wpa_qmi_ssr);
+        if(wpa_qmi_ssr) {
+                eap_proxy = eapol_ctx;
+        } else {
+                eap_proxy =  os_malloc(sizeof(struct eap_proxy_sm));
+                if (NULL == eap_proxy) {
+                        wpa_printf(MSG_ERROR, "Error memory alloc  for eap_proxy"
+                                "eap_proxy_init\n");
+                        return NULL;
+                }
+                os_memset(eap_proxy, 0, sizeof(*eap_proxy));
+                eap_proxy->ctx = eapol_ctx;
+                eap_proxy->eapol_cb = eapol_cb;
+                eap_proxy->msg_ctx = msg_ctx;
+        }
+
+        eap_proxy->proxy_state = EAP_PROXY_DISABLED;
+        eap_proxy->qmi_state = QMI_STATE_IDLE;
+        eap_proxy->key = NULL;
+        eap_proxy->iskey_valid = FALSE;
+        eap_proxy->is_state_changed = FALSE;
+        eap_proxy->isEap = FALSE;
+        eap_proxy->eap_type = EAP_TYPE_NONE;
+
+        /* delay the qmi client initialization after the eloop_run starts,
+        * in order to avoid the case of daemonize enabled, which exits the
+        * parent process that created the qmi client context.
+        */
+
+        eloop_register_timeout(0, 0, eap_proxy_schedule_thread, eap_proxy, NULL);
+        return eap_proxy;
+}
+
+
+static void eap_proxy_qmi_deinit(struct eap_proxy_sm *eap_proxy)
+{
+        int qmiRetCode;
+        int qmiErrorCode;
+        int index;
+        wpa_uim_struct_type *wpa_uim = eap_proxy->wpa_uim;
+
+        if (NULL == eap_proxy)
+                return;
+
+        pthread_kill(eap_proxy->thread_id, SIGUSR1);
+        eap_proxy->proxy_state = EAP_PROXY_DISABLED;
+
+        for (index = 0; index < MAX_NO_OF_SIM_SUPPORTED; ++index) {
+                if (TRUE == eap_proxy->eap_auth_session_flag[index]) {
+
+                        /* end the current EAP session */
+                        if(eap_auth_end_eap_session(eap_proxy->qmi_auth_svc_client_ptr[index]) < 0 ){
+                                wpa_printf(MSG_ERROR, "eap_proxy: Unable to end the EAP session for"
+                                                " client %d", index+1);
+                        } else {
+                                wpa_printf(MSG_ERROR, "eap_proxy: Ended the QMI EAP session for "
+                                                "client %d\n",
+                                                index+1);
+                                eap_proxy->eap_auth_session_flag[index] = FALSE;
+                        }
+                } else {
+                        wpa_printf (MSG_ERROR, "eap_proxy: session not started"
+                                " for client = %d\n", index+1);
+                        continue;
+                }
+
+                if ((TRUE == eap_proxy->qmi_uim_svc_client_initialized[index]))  {
+                        qmiRetCode = qmi_client_release(wpa_uim[index].qmi_uim_svc_client_ptr);
+                        if (QMI_NO_ERR != qmiRetCode) {
+                                wpa_printf (MSG_ERROR, "eap_proxy: Unable to Releas the connection"
+                                                " to uim service for client=%d; error_ret=%d\n;",
+                                                index+1, qmiRetCode);
+                        }
+                        wpa_printf(MSG_ERROR, "eap_proxy: Released QMI UIM service client\n");
+                        eap_proxy->qmi_uim_svc_client_initialized[index] = FALSE;
+                }
+
+                qmiRetCode = qmi_client_release(eap_proxy->qmi_auth_svc_client_ptr[index]);
+                if (QMI_NO_ERR != qmiRetCode) {
+                        wpa_printf (MSG_ERROR, "eap_proxy: Unable to Releas the connection"
+                                        " to auth service for client=%d; error_ret=%d\n;",
+                                        index+1, qmiRetCode);
+                }  else {
+                        wpa_printf(MSG_ERROR, "eap_proxy: Released QMI EAP service client\n");
+                }
+
+        }
+
+        if (NULL != eap_proxy->key) {
+                os_free(eap_proxy->key);
+                eap_proxy->key = NULL;
+        }
+
+        eap_proxy->iskey_valid = FALSE;
+        eap_proxy->is_state_changed = FALSE;
+        eap_proxy->user_selected_sim = 0;
+
+}
+
+void eap_proxy_deinit(struct eap_proxy_sm *eap_proxy)
+{
+        eap_proxy_qmi_deinit(eap_proxy);
+        if (eap_proxy != NULL) {
+            os_free(eap_proxy);
+            eap_proxy = NULL;
+            wpa_printf(MSG_INFO, "eap_proxy: eap_proxy Deinitialzed\n");
+        }
+}
+
+/* Call-back function to process an authentication result indication
+*  from QMI EAP service */
+static void handle_qmi_eap_ind(qmi_client_type user_handle,
+                               unsigned int msg_id,
+                               void* ind_buf,
+                               unsigned int ind_buf_len,
+                               void* ind_cb_data)
+{
+        qmi_client_error_type qmi_err;
+        auth_eap_session_result_ind_msg_v01 eap_session_result;
+        memset(&eap_session_result, 0, sizeof(auth_eap_session_result_ind_msg_v01));
+        eap_session_result.eap_result = -1;
+        struct eap_proxy_sm *sm = (struct eap_proxy_sm *)ind_cb_data;
+
+        auth_eap_notification_code_ind_msg_v01 eap_notification;
+        memset(&eap_notification, 0, sizeof(auth_eap_notification_code_ind_msg_v01));
+
+        wpa_printf(MSG_ERROR, "eap_proxy: Handle_qmi_eap_ind msgId =%d  sm=%p\n", msg_id,sm);
+        /* Decode */
+
+        switch(msg_id)
+        {
+                case QMI_AUTH_EAP_SESSION_RESULT_IND_V01:
+
+                        qmi_err = qmi_client_message_decode(user_handle, QMI_IDL_INDICATION,
+                                        msg_id, (void*)ind_buf, ind_buf_len,
+                                        &eap_session_result,
+                                        sizeof(auth_eap_session_result_ind_msg_v01));
+                        if (qmi_err != QMI_NO_ERR)
+                        {
+                                wpa_printf(MSG_ERROR, "eap_proxy: Error in qmi_client_message_de"
+                                        "code; error_code=%d \n", qmi_err);
+                                sm->srvc_result = EAP_PROXY_QMI_SRVC_FAILURE;
+                                return;
+                        }
+                        if ((eap_session_result.eap_result == 0) &&
+                            (QMI_STATE_RESP_TIME_OUT != sm->qmi_state)) {
+                                sm->proxy_state = EAP_PROXY_AUTH_SUCCESS;
+                                sm->qmi_state = QMI_STATE_RESP_RECEIVED;
+                                wpa_printf(MSG_ERROR, "eap_proxy: Handle_qmi_eap_ind EAP PROXY AUTH"
+                                        " SUCCESS %p set to %d\n",
+                                        (void *)&sm->qmi_state, sm->qmi_state);
+                        } else {
+                                sm->proxy_state = EAP_PROXY_AUTH_FAILURE;
+                                wpa_printf(MSG_ERROR, "eap_proxy: Handle_qmi_eap_ind EAP PROXY AUTH"
+                                        " FAILURE \n");
+                        }
+                        sm->srvc_result = EAP_PROXY_QMI_SRVC_SUCCESS;
+                        break;
+
+                case QMI_AUTH_EAP_NOTIFICATION_CODE_IND_V01:
+
+                        qmi_err = qmi_client_message_decode(user_handle, QMI_IDL_INDICATION,
+                                        msg_id, (void*)ind_buf, ind_buf_len,
+                                        &eap_notification,
+                                        sizeof(auth_eap_notification_code_ind_msg_v01));
+                        if (qmi_err != QMI_NO_ERR)
+                        {
+                                wpa_printf(MSG_ERROR, "eap_proxy: Error in qmi_client_"
+                                        "message_decode; error_code=%d \n", qmi_err);
+                        }
+                        sm->notification_code = eap_notification.eap_notification_code;
+                        wpa_printf(MSG_ERROR, "eap_proxy: notificatio code is %x\n",
+                                        eap_notification.eap_notification_code);
+                        break;
+
+                default:
+                        wpa_printf(MSG_ERROR, "eap_proxy: An unexpected msg Id=%d"
+                                        " is given\n", msg_id);
+                        break;
+        }
+
+
+}
+
+
+/* Call-back function to process an EAP response from QMI EAP service */
+static void handle_qmi_eap_reply(
+                qmi_client_type userHandle, unsigned int msg_id,
+                void *resp_c_struct, unsigned int resp_c_struct_len,
+                void *userData, qmi_client_error_type sysErrCode)
+{
+        struct eap_proxy_sm *eap_proxy = (struct eap_proxy_sm *)userData;
+        auth_send_eap_packet_resp_msg_v01* rspData =
+                (auth_send_eap_packet_resp_msg_v01*)resp_c_struct;
+
+        u8 *resp_data;
+        u32 length;
+
+        wpa_printf(MSG_ERROR, "eap_proxy: %s started\n", __func__);
+        if (eap_proxy == NULL) {
+                wpa_printf(MSG_ERROR, "eap_proxy: eap_proxy is NULL");
+                return;
+        }
+        if (QMI_STATE_RESP_PENDING == eap_proxy->qmi_state) {
+
+                wpa_printf(MSG_ERROR, "eap_proxy: user_selected_sim = %d\n",
+                           eap_proxy->user_selected_sim+1);
+
+
+                if (QMI_NO_ERR != sysErrCode) {
+                        wpa_printf(MSG_ERROR, "eap_proxy: An error is encountered with"
+                                        " the request: sysErrorCode=%d\n",
+                                        sysErrCode);
+                        eap_proxy->qmi_state = QMI_STATE_RESP_TIME_OUT;
+                        return;
+                }
+
+                if (NULL == rspData) {
+                        wpa_printf(MSG_ERROR, "eap_proxy: Response data is NULL\n");
+                        eap_proxy->qmi_state = QMI_STATE_RESP_TIME_OUT;
+                        return;
+                }
+                if((QMI_AUTH_SEND_EAP_PACKET_REQ_V01 != msg_id) &&
+                   (QMI_AUTH_SEND_EAP_PACKET_EXT_REQ_V01 != msg_id))
+                {
+                        wpa_printf(MSG_ERROR, "eap_proxy: Invalid msgId =%d\n", msg_id);
+                        eap_proxy->qmi_state = QMI_STATE_RESP_TIME_OUT;
+                        return;
+                }
+
+                /* ensure the reply packet exists  */
+                if (rspData->eap_response_pkt_len <= 0 ||
+                    rspData->eap_response_pkt_len > QMI_AUTH_EAP_RESP_PACKET_EXT_MAX_V01) {
+                        wpa_printf(MSG_ERROR, "eap_proxy: Reply packet is of invalid length %d"
+                                " error %d result %d\n", rspData->eap_response_pkt_len,
+                                rspData->resp.error, rspData->resp.result);
+                        eap_proxy->qmi_state = QMI_STATE_RESP_TIME_OUT;
+                        return;
+                }
+
+                length = rspData->eap_response_pkt_len;
+                eap_proxy->qmi_resp_data.eap_send_pkt_resp.length = length;
+                /* allocate a buffer to store the response data; size is EAP resp len field */
+                eap_proxy->qmi_resp_data.eap_send_pkt_resp.resp_data =
+                        os_malloc(rspData->eap_response_pkt_len);
+
+                resp_data =
+                        (u8 *)eap_proxy->qmi_resp_data.eap_send_pkt_resp.resp_data;
+
+                if (NULL == resp_data) {
+                        wpa_printf(MSG_ERROR, "eap_proxy: Unable to allocate memory for"
+                                        " reply packet\n");
+                        eap_proxy->qmi_state = QMI_STATE_RESP_TIME_OUT;
+
+                        return;
+                }
+
+                /* copy the response data to the allocated buffer */
+                os_memcpy(resp_data,
+                                rspData->eap_response_pkt, length);
+                eap_proxy->qmi_state = QMI_STATE_RESP_RECEIVED;
+                wpa_printf(MSG_ERROR, "eap_proxy: **HANDLE_QMI_EAP_REPLY CALLBACK ENDDED **");
+
+                wpa_printf(MSG_ERROR, "eap_proxy: Dump Resp Data len %d\n", length);
+                dump_buff(resp_data, length);
+        }
+
+        return;
+}
+
+static enum eap_proxy_status eap_proxy_process(struct eap_proxy_sm  *eap_proxy,
+                                        u8 *eapReqData, int eapReqDataLen, struct eap_sm *eap_sm)
+{
+        struct eap_hdr *hdr;
+        int qmiErrorCode;
+        enum eap_proxy_status proxy_status = EAP_PROXY_SUCCESS;
+        auth_send_eap_packet_req_msg_v01 eap_send_packet_req;
+        auth_send_eap_packet_resp_msg_v01 eap_send_packet_resp;
+        qmi_txn_handle async_txn_hdl = 0;
+
+        auth_send_eap_packet_ext_req_msg_v01 eap_send_packet_ext_req;
+        auth_send_eap_packet_ext_resp_msg_v01 eap_send_packet_ext_resp;
+
+
+        hdr = (struct eap_hdr *)eapReqData;
+        if ((EAP_CODE_REQUEST == hdr->code) &&
+            (EAP_TYPE_IDENTITY == eapReqData[4])) {
+                if (eap_proxy_eapol_sm_get_bool(eap_proxy, EAPOL_eapRestart) &&
+                    eap_proxy_eapol_sm_get_bool(eap_proxy, EAPOL_portEnabled)) {
+                        wpa_printf (MSG_ERROR, "eap_proxy: Already Authenticated."
+                                    " Clear all the flags");
+                        eap_proxy_eapol_sm_set_bool(eap_proxy, EAPOL_eapSuccess, FALSE);
+                        eap_proxy_eapol_sm_set_bool(eap_proxy, EAPOL_eapFail, FALSE);
+                        eap_proxy_eapol_sm_set_bool(eap_proxy, EAPOL_eapResp, FALSE);
+                        eap_proxy_eapol_sm_set_bool(eap_proxy, EAPOL_eapNoResp, FALSE);
+                        if (eap_proxy->key) {
+                                os_free(eap_proxy->key);
+                                eap_proxy->key = NULL;
+                        }
+                        eap_proxy->iskey_valid = FALSE;
+                        eap_proxy->is_state_changed = TRUE;
+                }
+                eap_proxy_eapol_sm_set_bool(eap_proxy, EAPOL_eapRestart, FALSE);
+
+                if(eap_proxy_build_identity(eap_proxy, hdr->identifier, eap_sm)) {
+                        eap_proxy->proxy_state = EAP_PROXY_IDENTITY;
+                } else {
+                        wpa_printf(MSG_ERROR, "eap_proxy: Error in build identity\n");
+                        return EAP_PROXY_FAILURE;
+                }
+        }
+        wpa_printf(MSG_ERROR, "eap_proxy: ***********Dump ReqData len %d***********",
+                eapReqDataLen);
+        dump_buff(eapReqData, eapReqDataLen);
+        if (eapReqDataLen <= QMI_AUTH_EAP_REQ_PACKET_MAX_V01) {
+                os_memset(&eap_send_packet_req, 0, sizeof(auth_send_eap_packet_req_msg_v01));
+                os_memset(&eap_send_packet_resp, 0, sizeof(auth_send_eap_packet_resp_msg_v01));
+                eap_send_packet_req.eap_request_pkt_len = eapReqDataLen ;
+                memcpy(eap_send_packet_req.eap_request_pkt, eapReqData, eapReqDataLen);
+        } else if (eapReqDataLen <= QMI_AUTH_EAP_REQ_PACKET_EXT_MAX_V01) {
+                os_memset(&eap_send_packet_ext_req, 0,
+                        sizeof(auth_send_eap_packet_ext_req_msg_v01));
+                os_memset(&eap_send_packet_ext_resp, 0,
+                        sizeof(auth_send_eap_packet_ext_resp_msg_v01));
+                eap_send_packet_ext_req.eap_request_ext_pkt_len = eapReqDataLen;
+                memcpy(eap_send_packet_ext_req.eap_request_ext_pkt, eapReqData, eapReqDataLen);
+        } else {
+                        wpa_printf(MSG_ERROR, "eap_proxy: Error in eap_send_packet_req\n");
+                        return EAP_PROXY_FAILURE;
+        }
+
+        wpa_printf(MSG_ERROR, "eap_proxy: SIM selected by User: Selected sim = %d\n",
+                eap_proxy->user_selected_sim+1);
+        if (eap_proxy->qmi_state != QMI_STATE_IDLE) {
+                wpa_printf(MSG_ERROR, "Error in QMI state=%d\n",
+                                         eap_proxy->qmi_state);
+                return EAP_PROXY_FAILURE;
+        }
+
+        wpa_printf (MSG_ERROR, "eap_proxy: In eap_proxy_process case %d\n", hdr->code);
+        eap_proxy->qmi_state = QMI_STATE_RESP_PENDING;
+
+        if(eapReqDataLen <= QMI_AUTH_EAP_REQ_PACKET_MAX_V01) {
+                qmiErrorCode = qmi_client_send_msg_async(
+                                eap_proxy->qmi_auth_svc_client_ptr[eap_proxy->user_selected_sim],
+                                QMI_AUTH_SEND_EAP_PACKET_REQ_V01,
+                                (void *) &eap_send_packet_req,
+                                sizeof(auth_send_eap_packet_req_msg_v01),
+                                (void *) &eap_send_packet_resp,
+                                sizeof(auth_send_eap_packet_resp_msg_v01),
+                                &handle_qmi_eap_reply, eap_proxy,
+                                &async_txn_hdl);
+        } else if(eapReqDataLen <= QMI_AUTH_EAP_REQ_PACKET_EXT_MAX_V01) {
+                qmiErrorCode = qmi_client_send_msg_async(
+                                eap_proxy->qmi_auth_svc_client_ptr[eap_proxy->user_selected_sim],
+                                QMI_AUTH_SEND_EAP_PACKET_EXT_REQ_V01,
+                                (void *) &eap_send_packet_ext_req,
+                                sizeof(auth_send_eap_packet_ext_req_msg_v01),
+                                (void *) &eap_send_packet_ext_resp,
+                                sizeof(auth_send_eap_packet_ext_resp_msg_v01),
+                                &handle_qmi_eap_reply, eap_proxy,
+                                &async_txn_hdl);
+        }
+
+        if (QMI_NO_ERR != qmiErrorCode) {
+                wpa_printf(MSG_ERROR, "QMI-ERROR Error in sending EAP packet;"
+                                " error_code=%d\n", qmiErrorCode);
+                eap_proxy->proxy_state = EAP_PROXY_DISCARD;
+                eap_proxy_eapol_sm_set_bool(eap_proxy, EAPOL_eapNoResp, TRUE);
+                eap_proxy->qmi_state = QMI_STATE_RESP_PENDING;
+                return EAP_PROXY_FAILURE;
+        } else {
+                wpa_printf (MSG_ERROR, "eap_proxy: In eap_proxy_process case %d\n", hdr->code);
+                switch (hdr->code) {
+                case EAP_CODE_SUCCESS:
+                        if (EAP_PROXY_SUCCESS !=
+                                eap_proxy_qmi_response_wait(eap_proxy)) {
+                                eap_proxy->proxy_state = EAP_PROXY_DISCARD;
+                                eap_proxy_eapol_sm_set_bool(eap_proxy,
+                                                        EAPOL_eapNoResp, TRUE);
+                                return EAP_PROXY_FAILURE;
+                        } else if( eap_proxy->proxy_state == EAP_PROXY_AUTH_SUCCESS ) {
+                                eap_proxy_getKey(eap_proxy);
+                                eap_proxy_eapol_sm_set_bool(eap_proxy,
+                                                 EAPOL_eapSuccess, TRUE);
+        /*
+         * RFC 4137 does not clear eapReq here, but this seems to be required
+         * to avoid processing the same request twice when state machine is
+         * initialized.
+         */
+                        eap_proxy_eapol_sm_set_bool(eap_proxy,
+                                                        EAPOL_eapReq, FALSE);
+
+        /*
+         * RFC 4137 does not set eapNoResp here, but this seems to be required
+         * to get EAPOL Supplicant backend state machine into SUCCESS state. In
+         * addition, either eapResp or eapNoResp is required to be set after
+         * processing the received EAP frame.
+         */
+                        eap_proxy_eapol_sm_set_bool(eap_proxy,
+                                                EAPOL_eapNoResp, TRUE);
+
+                        wpa_msg(eap_proxy->msg_ctx, MSG_INFO, WPA_EVENT_EAP_SUCCESS
+                                "eap_proxy: EAP authentication completed successfully");
+
+                        eap_proxy->is_state_changed = TRUE;
+
+                                /* Retrieve the keys  and store*/
+                        } else if( eap_proxy->proxy_state == EAP_PROXY_AUTH_FAILURE ){
+
+                                eap_proxy_eapol_sm_set_bool(eap_proxy,
+                                                EAPOL_eapFail, TRUE);
+                                eap_proxy_eapol_sm_set_bool(eap_proxy,
+                                                EAPOL_eapReq, FALSE);
+                                eap_proxy_eapol_sm_set_bool(eap_proxy,
+                                                EAPOL_eapNoResp, TRUE);
+                                eap_proxy->is_state_changed = TRUE;
+
+                        }
+
+                        break;
+
+                case EAP_CODE_FAILURE:
+                        wpa_printf (MSG_ERROR,
+                                "eap_proxy: in eap_proxy_process case EAP_CODE_FAILURE\n");
+                        eap_proxy->proxy_state = EAP_PROXY_AUTH_FAILURE;
+                        eap_proxy_eapol_sm_set_bool(eap_proxy,
+                                                EAPOL_eapFail, TRUE);
+
+        /*
+         * RFC 4137 does not clear eapReq here, but this seems to be required
+         * to avoid processing the same request twice when state machine is
+         * initialized.
+        */
+                        eap_proxy_eapol_sm_set_bool(eap_proxy,
+                                                EAPOL_eapReq, FALSE);
+
+        /*
+         * RFC 4137 does not set eapNoResp here. However, either eapResp or
+         * eapNoResp is required to be set after processing the received EAP
+         * frame.
+         */
+                        eap_proxy_eapol_sm_set_bool(eap_proxy,
+                                                EAPOL_eapNoResp, TRUE);
+
+                        wpa_msg(eap_proxy->msg_ctx, MSG_INFO, WPA_EVENT_EAP_FAILURE
+                                "EAP authentication failed notification code 0x%x",
+                                eap_proxy->notification_code);
+
+                        eap_proxy->is_state_changed = TRUE;
+                        break;
+
+                case EAP_CODE_REQUEST:
+                                        eap_proxy->proxy_state = EAP_PROXY_SEND_RESPONSE;
+                        if (EAP_PROXY_SUCCESS !=
+                                eap_proxy_qmi_response_wait(eap_proxy)) {
+                                eap_proxy->proxy_state = EAP_PROXY_DISCARD;
+                                eap_proxy_eapol_sm_set_bool(eap_proxy,
+                                                        EAPOL_eapNoResp, TRUE);
+                                return EAP_PROXY_FAILURE;
+                        } else {
+                                eap_proxy_eapol_sm_set_bool(eap_proxy,
+                                                        EAPOL_eapResp, TRUE);
+                                eap_proxy->proxy_state =
+                                                EAP_PROXY_SEND_RESPONSE;
+                        }
+
+                        eap_proxy_eapol_sm_set_bool(eap_proxy,
+                                                EAPOL_eapReq, FALSE);
+                        eap_proxy->is_state_changed = TRUE;
+                        break;
+
+                default:
+                        wpa_printf(MSG_ERROR, "eap_proxy: Error in sending EAP packet;"
+                                         " error_code=%d\n", qmiErrorCode);
+                        eap_proxy->proxy_state = EAP_PROXY_DISCARD;
+                        eap_proxy_eapol_sm_set_bool(eap_proxy,
+                                EAPOL_eapNoResp, TRUE);
+                        return EAP_PROXY_FAILURE;
+                }
+        }
+
+        return EAP_PROXY_SUCCESS;
+}
+
+
+
+static u8 *eap_proxy_getKey(struct eap_proxy_sm *eap_proxy)
+{
+        int qmiErrorCode;
+        int qmiRetCode;
+
+        auth_get_eap_session_keys_resp_msg_v01 key_resp_msg;
+        os_memset(&key_resp_msg, 0, sizeof(auth_get_eap_session_keys_resp_msg_v01));
+
+        qmiRetCode = qmi_client_send_msg_sync(
+                        eap_proxy->qmi_auth_svc_client_ptr[eap_proxy->user_selected_sim],
+                        QMI_AUTH_GET_EAP_SESSION_KEYS_REQ_V01,
+                        NULL,
+                        0,
+                        (void *) &key_resp_msg,
+                        sizeof(auth_get_eap_session_keys_resp_msg_v01),
+                        WPA_UIM_QMI_DEFAULT_TIMEOUT);
+
+
+        /* see if the MSK is acquired successfully */
+        if (QMI_NO_ERR != qmiRetCode || key_resp_msg.resp.result != QMI_RESULT_SUCCESS_V01) {
+                wpa_printf(MSG_ERROR, "QMI-ERROR Unable to get session keys;"
+                                 " err_code=%d qmiErr=%d\n", qmiRetCode, key_resp_msg.resp.error);
+                eap_proxy->key = NULL;
+                return NULL;
+        }
+        wpa_printf(MSG_ERROR, "eap_proxy: %s:session_key_len =%d", __func__,
+                key_resp_msg.session_key_len);
+
+        if(key_resp_msg.session_key_len <=0 ||
+           key_resp_msg.session_key_len > EAP_PROXY_KEYING_DATA_LEN)
+        {
+                return NULL;
+
+        }
+        eap_proxy->key = os_malloc(EAP_PROXY_KEYING_DATA_LEN);
+        if(eap_proxy->key == NULL)
+                return NULL;
+
+        memset(eap_proxy->key, 0, EAP_PROXY_KEYING_DATA_LEN);
+        memcpy(eap_proxy->key, key_resp_msg.session_key, key_resp_msg.session_key_len);
+
+        eap_proxy->iskey_valid = TRUE;
+        eap_proxy->proxy_state = EAP_PROXY_AUTH_SUCCESS;
+
+        wpa_printf(MSG_ERROR, "eap_proxy: eap_proxy_getkey EAP KEYS ");
+        dump_buff(eap_proxy->key, EAP_PROXY_KEYING_DATA_LEN);
+        return eap_proxy->key;
+}
+
+
+/**
+ * eap_key_available - Get key availability (eapKeyAvailable variable)
+ * @sm: Pointer to EAP state machine allocated with eap_sm_init()
+ * Returns: 1 if EAP keying material is available, 0 if not
+ */
+int eap_proxy_key_available(struct eap_proxy_sm *sm)
+{
+        return sm ? sm->iskey_valid : 0;
+}
+
+
+static int eap_proxy_is_state_changed(struct eap_proxy_sm *sm)
+{
+        if (NULL == sm)
+                return 0;
+
+        if (TRUE == sm->is_state_changed) {
+                sm->is_state_changed = FALSE;
+                return 1;
+        } else {
+                return 0;
+        }
+}
+
+
+/**
+ * eap_get_eapKeyData - Get master session key (MSK) from EAP state machine
+ * @sm: Pointer to EAP state machine allocated with eap_sm_init()
+ * @len: Pointer to variable that will be set to number of bytes in the key
+ * Returns: Pointer to the EAP keying data or %NULL on failure
+ *
+ * Fetch EAP keying material (MSK, eapKeyData) from the EAP state machine. The
+ * key is available only after a successful authentication. EAP state machine
+ * continues to manage the key data and the caller must not change or free the
+ * returned data.
+ */
+const u8 * eap_proxy_get_eapKeyData(struct eap_proxy_sm *sm, size_t *len)
+{
+        if (sm == NULL || sm->key == NULL) {
+                *len = 0;
+                return NULL;
+        }
+
+        *len = EAP_PROXY_KEYING_DATA_LEN;
+        return sm->key;
+}
+
+/**
+ * eap_proxy_get_eapRespData - Get EAP response data
+ * @sm: Pointer to EAP state machine allocated with eap_sm_init()
+ * @len: Pointer to variable that will be set to the length of the response
+ * Returns: Pointer to the EAP response (eapRespData) or %NULL on failure
+ *
+ * Fetch EAP response (eapRespData) from the EAP state machine. This data is
+ * available when EAP state machine has processed an incoming EAP request. The
+ * EAP state machine does not maintain a reference to the response after this
+ * function is called and the caller is responsible for freeing the data.
+ */
+struct wpabuf * eap_proxy_get_eapRespData(struct eap_proxy_sm *eap_proxy)
+{
+        struct wpabuf *resp;
+        int len;
+        //int i;
+
+        wpa_printf(MSG_ERROR, "eap_proxy: eap_proxy_get_eapRespData");
+        if ( (eap_proxy == NULL) ||
+             (eap_proxy->qmi_resp_data.eap_send_pkt_resp.resp_data == NULL)
+           )
+        {
+                return NULL;
+        }
+
+        len = eap_proxy->qmi_resp_data.eap_send_pkt_resp.length;
+        wpa_printf(MSG_ERROR, "eap_proxy: eap_proxy_get_eapRespData len = %d", len);
+        resp = wpabuf_alloc(len);
+        if (resp == NULL) {
+                wpa_printf(MSG_ERROR, "eap_proxy: buf allocation failed\n");
+                return NULL;
+        }
+
+        resp->used = len;
+        os_memcpy(resp->buf, eap_proxy->qmi_resp_data.eap_send_pkt_resp.resp_data,
+                   len);
+        /*
+        for (i = 0; i < len; i++) {
+                wpa_printf (MSG_ERROR, "%c", resp->buf[i]);
+        }
+        */
+        os_free(eap_proxy->qmi_resp_data.eap_send_pkt_resp.resp_data);
+        eap_proxy->qmi_resp_data.eap_send_pkt_resp.resp_data = NULL;
+        eap_proxy->qmi_resp_data.eap_send_pkt_resp.length = 0;
+
+        return resp;
+}
+
+
+static enum eap_proxy_status eap_proxy_qmi_response_wait(struct eap_proxy_sm *eap_proxy)
+{
+
+        int count = 0;
+
+        wpa_printf(MSG_DEBUG, "eap_proxy_qmi_response_wait: Start blocking "
+                   "wait eap_proxy=%p",eap_proxy);
+        do {
+                count++;
+                if (count > QMI_RESP_TIME_OUT / 2) {
+                        wpa_printf(MSG_ERROR,
+                                   "eap_proxy: eap_proxy_qmi_response_wait "
+                                   "!QMI STATE %d TIME_OUT\n",
+                                   eap_proxy->qmi_state);
+                        eap_proxy->qmi_state = QMI_STATE_RESP_TIME_OUT;
+                        break;
+                }
+
+                os_sleep(0, 2000);
+
+                if ((QMI_STATE_RESP_RECEIVED == eap_proxy->qmi_state) ||
+                   (QMI_STATE_RESP_TIME_OUT == eap_proxy->qmi_state))
+                        break;
+        } while (1);
+
+        wpa_printf(MSG_DEBUG, "eap_proxy: eap_proxy_qmi_response_wait: Wait done after %d "
+                   "iterations: qmi_state=%d", count,
+                   eap_proxy->qmi_state);
+
+        if (QMI_STATE_RESP_TIME_OUT == eap_proxy->qmi_state) {
+                wpa_printf(MSG_ERROR, "eap_proxy: QMI state Response Time out\n");
+                eap_proxy->proxy_state = EAP_PROXY_DISCARD;
+                return EAP_PROXY_FAILURE;
+        }
+        eap_proxy->qmi_state = QMI_STATE_IDLE;
+
+        return EAP_PROXY_SUCCESS;
+}
+
+
+static void eap_proxy_eapol_sm_set_bool(struct eap_proxy_sm *sm,
+                        enum eapol_bool_var var, Boolean value)
+{
+        sm->eapol_cb->set_bool(sm->ctx, var, value);
+}
+
+
+static Boolean eap_proxy_eapol_sm_get_bool(struct eap_proxy_sm *sm,
+                         enum eapol_bool_var var)
+{
+        return  sm->eapol_cb->get_bool(sm->ctx, var);
+}
+
+
+int eap_proxy_sm_step(struct eap_proxy_sm *sm, struct eap_sm *eap_sm)
+{
+        if ((sm->proxy_state != EAP_PROXY_INITIALIZE) &&
+                                 (sm->proxy_state != EAP_PROXY_DISABLED)) {
+                if (TRUE == sm->isEap) {
+                        if(!eap_proxy_process(sm, sm->eapReqData,
+                                                 sm->eapReqDataLen,eap_sm)) {
+                                sm->proxy_state = EAP_PROXY_AUTH_FAILURE;
+                                eap_proxy_eapol_sm_set_bool(sm, EAPOL_eapRestart, TRUE);
+                        }
+                        sm->isEap = FALSE;
+                }
+        }
+        return eap_proxy_is_state_changed(sm);
+}
+
+
+enum eap_proxy_status
+eap_proxy_packet_update(struct eap_proxy_sm *eap_proxy, u8 *eapReqData,
+                        int eapReqDataLen)
+{
+        eap_proxy->eapReqData = eapReqData;
+        eap_proxy->eapReqDataLen = eapReqDataLen;
+        eap_proxy->isEap = TRUE;
+        return EAP_PROXY_SUCCESS;
+}
+
+
+u8 * eap_proxy_get_eap_session_id(struct eap_proxy_sm *sm, size_t *len)
+{
+        wpa_printf(MSG_ERROR, "%s: enter: not implemented\n", __func__);
+        return NULL;
+}
+
+
+u8 * eap_proxy_get_emsk(struct eap_proxy_sm *sm, size_t *len)
+{
+        wpa_printf(MSG_ERROR, "%s: enter: not implemented\n", __func__);
+        return NULL;
+}
+
+
+void eap_proxy_sm_abort(struct eap_proxy_sm *sm)
+{
+        wpa_printf(MSG_ERROR, "%s: enter: not implemented\n", __func__);
+        return;
+}
+
+
+static void dump_buff(u8 *buff, int len)
+{
+        int i ;
+
+        wpa_printf(MSG_ERROR, "eap_proxy: ---- EAP Buffer----LEN %d\n",len);
+        for (i = 0; i < len; i++) {
+                if (0 == i%8)
+                        wpa_printf(MSG_DEBUG, " \n");
+                wpa_printf(MSG_ERROR, "eap_proxy: 0x%x  ", buff[i]);
+        }
+        return;
+}
+static char bin_to_hexchar(u8 ch)
+{
+        if (ch < 0x0a) {
+                return ch + '0';
+        }
+        return ch + 'a' - 10;
+}
+static Boolean eap_proxy_build_identity(struct eap_proxy_sm *eap_proxy, u8 id, struct eap_sm *eap_sm)
+{
+        struct eap_hdr *resp;
+        unsigned int len;
+        u8 identity_len = 0, ret;
+        u8 imsi_id_len = 0;
+        int mnc_len = -1;
+        u8 *pos;
+        int qmiRetCode;
+        u8 idx = 0, mcc_idx = 0;
+        unsigned char *identity = NULL;
+        unsigned char *imsi_identity = NULL;
+        auth_start_eap_session_req_msg_v01 eap_auth_start;
+        auth_start_eap_session_resp_msg_v01 eap_auth_start_resp;
+        auth_set_subscription_binding_req_msg_v01 sub_req_binding;
+        auth_set_subscription_binding_resp_msg_v01 sub_resp_binding;
+
+        struct eap_method_type *m;
+        eap_identity_format_e identity_format = EAP_IDENTITY_ANNONYMOUS;
+        Boolean simEnabled = FALSE, akaEnabled = FALSE;
+        struct eap_peer_config *config = eap_get_config(eap_sm);
+        const char *realm_3gpp = "@wlan.mnc000.mcc000.3gppnetwork.org";
+        int sim_num;
+
+        wpa_printf(MSG_ERROR, "eap_proxy: %s\n", __func__);
+        sim_num = config->sim_num - 1;
+        os_memset(&eap_auth_start, 0, sizeof(eap_auth_start));
+        os_memset(&eap_auth_start_resp, 0, sizeof(eap_auth_start_resp));
+
+        eap_auth_start.user_id_len = 0;
+        m = config->eap_methods;
+
+        if (sim_num >= MAX_NO_OF_SIM_SUPPORTED || sim_num < 0) {
+                wpa_printf (MSG_ERROR, "eap_proxy: Invalid SIM selected sim by user = %d\n",
+                             sim_num+1);
+                return FALSE;
+        }
+        wpa_printf(MSG_ERROR, "eap_proxy: User selected sim = %d\n", sim_num + 1);
+
+        if (m != NULL) {
+                for (idx = 0; m[idx].vendor != EAP_VENDOR_IETF ||
+                                m[idx].method != EAP_TYPE_NONE; idx++) {
+                        if (m[idx].method == EAP_TYPE_AKA) {
+                                akaEnabled = TRUE;
+                                eap_auth_start.eap_method_mask_valid = 1;
+                                eap_auth_start.eap_method_mask |= QMI_AUTH_EAP_METHOD_MASK_AKA_V01;
+                                wpa_printf(MSG_ERROR, "eap_proxy: AKA Enabled\n");
+                        } else if (m[idx].method == EAP_TYPE_SIM) {
+                                simEnabled = TRUE;
+                                eap_auth_start.eap_method_mask_valid = 1;
+                                eap_auth_start.eap_method_mask |= QMI_AUTH_EAP_METHOD_MASK_SIM_V01;
+                                wpa_printf(MSG_ERROR, "eap_proxy: SIM Enabled\n");
+#ifdef CONFIG_EAP_PROXY_AKA_PRIME
+                        } else if (m[idx].method == EAP_TYPE_AKA_PRIME) {
+                                eap_auth_start.eap_method_mask_valid = 1;
+                                eap_auth_start.eap_method_mask |=
+                                        QMI_AUTH_EAP_METHOD_MASK_AKA_PRIME_V01;
+                                wpa_printf(MSG_ERROR, "eap_proxy: AKA Prime Enabled\n");
+#endif /* CONFIG_EAP_PROXY_AKA_PRIME */
+                        }
+                }
+        } else {
+                wpa_printf(MSG_ERROR, "eap_proxy: eap_methods is NULL!\n");
+                return FALSE;
+        }
+
+        eap_auth_start.eap_method_mask_valid = 1;
+
+        idx = 0;
+#ifdef SIM_AKA_IMSI_RAW_ENABLED
+
+        identity_format = EAP_IDENTITY_IMSI_RAW;
+        eap_auth_start.user_id_valid = 1;
+        wpa_printf(MSG_ERROR, "eap_proxy: EAP_IDENTITY_IMSI_RAW selected %d \n",
+                eap_auth_start.user_id_len);
+
+#else /* SIM_AKA_IMSI_RAW_ENABLED */
+
+        if (config->identity_len && config->identity != NULL) {
+                for (idx = 0; idx < config->identity_len; idx++) {
+                        if (config->identity[idx] == 64) {
+                                wpa_printf(MSG_ERROR, "eap_proxy: @ found \n");
+                                mcc_idx = idx;
+                                if ((mcc_idx + 18) > config->identity_len)
+                                        mcc_idx = 0;
+                                else {
+                                        /* Looking for mnc and mcc pattern */
+                                        if (109 == config->identity[mcc_idx + 6] &&
+                                                (110 == config->identity[mcc_idx + 7]) &&
+                                                (99 == config->identity[mcc_idx + 8]) &&
+                                                (109 == config->identity[mcc_idx + 13]) &&
+                                                (99 == config->identity[mcc_idx + 14]) &&
+                                                (99 == config->identity[mcc_idx + 15])) {
+                                                mcc_idx += 9;
+                                        } else
+                                                mcc_idx = 0;
+                                }
+                                break;
+                        }
+                }
+
+                wpa_printf(MSG_ERROR, "eap_proxy: idx %d\n", idx);
+                wpa_printf(MSG_ERROR, "eap_proxy: mcc idx %d\n", mcc_idx);
+
+                if (!idx && (config->identity_len == 1)) {
+                        /* config file : @ */
+                        config->identity_len = 0;
+                        identity_format = EAP_IDENTITY_IMSI_3GPP_REALM;
+                        wpa_printf(MSG_ERROR, "eap_proxy: EAP_IDENTITY_IMSI_3GPP_REALM "
+                                "selected \n");
+                } else if (idx && (idx < config->identity_len) && (config->identity != NULL)) {
+
+                        /* config file : <>@<> or <>@<wlan.mnc000.mcc000.<>.<> */
+                        identity_len = config->identity_len;
+                        identity = os_malloc(config->identity_len);
+
+                        if (NULL != identity) {
+                                os_memset(identity, 0, config->identity_len);
+                                os_memcpy(identity, config->identity,
+                                                config->identity_len);
+                        }
+
+                        /* To Do for 3GPP realm */
+                        identity_format = EAP_IDENTITY_CFG_3GPP_REALM;
+                        eap_auth_start.user_id_valid = 1;
+                        wpa_printf(MSG_ERROR, "eap_proxy: EAP_IDENTITY_CFG_3GPP_REALM "
+                                "selected %d \n", eap_auth_start.user_id_len);
+
+                } else if ((idx == config->identity_len) && config->identity_len &&
+                                        (config->identity != NULL)) {
+
+                        /* config file : <identity in RAW format >*/
+                        identity_len = config->identity_len;
+                        identity = os_malloc(config->identity_len);
+
+                        if (NULL != identity) {
+                                os_memset(identity, 0, config->identity_len);
+                                os_memcpy(identity, config->identity,
+                                                config->identity_len);
+                        }
+
+                        identity_format = EAP_IDENTITY_CFG_RAW;
+                        eap_auth_start.user_id_valid = 1;
+                        wpa_printf(MSG_ERROR, "eap_proxy: EAP_IDENTITY_CFG_RAW selected %d \n",
+                                eap_auth_start.user_id_len);
+                } else if (!idx && mcc_idx) {
+
+                        /* config file: @wlan.mnc000.mcc000.<>.<> */
+                        identity_len = config->identity_len;
+                        identity = os_malloc(config->identity_len);
+
+                        if (NULL != identity) {
+                                os_memset(identity, 0, config->identity_len);
+                                os_memcpy(identity, config->identity,
+                                         config->identity_len);
+                        }
+
+                        identity_format = EAP_IDENTITY_IMSI_3GPP_REALM;
+                        eap_auth_start.user_id_valid = 1;
+                        wpa_printf(MSG_ERROR, "eap_proxy: config EAP_IDENTITY_IMSI_3GPP_REALM "
+                                "selected %d\n", eap_auth_start.user_id_len);
+                }
+        } else {
+
+                if (config->anonymous_identity_len && config->anonymous_identity != NULL) {
+
+                        eap_auth_start.eap_meta_identity_len = config->anonymous_identity_len;
+                        os_memcpy(&eap_auth_start.eap_meta_identity ,
+                                                config->anonymous_identity ,
+                                                config->anonymous_identity_len);
+
+                        identity_format = EAP_IDENTITY_ANNONYMOUS;
+                        eap_auth_start.eap_meta_identity_valid = 1;
+                        wpa_printf(MSG_ERROR, "eap_proxy: EAP_IDENTITY_ANNONYMOUS selected user id "
+                                "%d, annonymous %d\n", eap_auth_start.user_id_len,
+                                eap_auth_start.eap_meta_identity_len);
+                } else {
+                        /* config file doesn't contain any identity
+                                generating IMSI@realm */
+                        identity_format = EAP_IDENTITY_IMSI_3GPP_REALM;
+                        eap_auth_start.user_id_valid = 1;
+                        wpa_printf(MSG_ERROR, "eap_proxy: EAP_IDENTITY_IMSI_3GPP_REALM id len %d\n",
+                                eap_auth_start.user_id_len);
+                }
+        }
+#endif /* SIM_AKA_IMSI_RAW_ENABLED */
+        if (identity_format == EAP_IDENTITY_IMSI_3GPP_REALM ||
+                identity_format == EAP_IDENTITY_IMSI_RAW || mcc_idx) {
+
+                wpa_printf(MSG_ERROR, "eap_proxy: EAP_IDENTITY_IMSI_3GPP_REALM is selected\n");
+                if (!wpa_qmi_read_card_status(sim_num, eap_proxy->wpa_uim)) {
+                        wpa_printf(MSG_INFO, "eap_proxy: Read Card Status failed, return\n");
+                        if (NULL != identity) {
+                                os_free(identity);
+                                identity = NULL;
+                        }
+                        return FALSE;
+                }
+
+                if (!wpa_qmi_read_card_imsi(sim_num, eap_proxy->wpa_uim)) {
+                        wpa_printf(MSG_INFO, "eap_proxy: Read Card IMSI failed, return\n");
+                        if (NULL != identity) {
+                                os_free(identity);
+                                identity = NULL;
+                        }
+                        return FALSE;
+                }
+
+                if (imsi == NULL) {
+                        wpa_printf(MSG_INFO, "eap_proxy: IMSI not available, return\n");
+                        if (NULL != identity) {
+                                os_free(identity);
+                                identity = NULL;
+                        }
+                        return FALSE;
+                } else {
+                        wpa_printf(MSG_ERROR, "eap_proxy: IMSI not NULL \n");
+                        if (NULL == identity)
+                                wpa_printf(MSG_ERROR,
+                                        "eap_proxy: config file doesn't contain identity \n");
+                        else
+                                wpa_printf(MSG_ERROR, "eap_proxy: config file contains identity\n");
+
+                        wpa_printf(MSG_ERROR, "eap_proxy: eap_type: %d\n", eap_proxy->eap_type);
+
+                        if (!idx) {
+
+                                /* IMSI is expected as username */
+                                wpa_printf(MSG_ERROR, "eap_proxy:  username is not available in"
+                                        " config picking IMSI \n");
+
+                                if (config->identity_len > 1)
+                                        /* @realm provided in config */
+                                        imsi_identity =
+                                                os_malloc(1 + IMSI_LENGTH + config->identity_len);
+                                else if (identity_format == EAP_IDENTITY_IMSI_3GPP_REALM)
+                                        /* IMSI@realm not provided through config */
+                                        imsi_identity =
+                                                os_malloc(1 + IMSI_LENGTH + os_strlen(realm_3gpp));
+                                else
+                                        /* IMSI RAW */
+                                        imsi_identity = os_malloc(1 + IMSI_LENGTH);
+
+                                if (NULL == imsi_identity) {
+                                        wpa_printf(MSG_ERROR, "eap_proxy: Memory not available\n");
+                                        if (NULL != identity) {
+                                                os_free(identity);
+                                                identity = NULL;
+                                        }
+                                        return FALSE;
+                                } else {
+                                        if (config->identity_len > 1)
+                                                os_memset(imsi_identity, 0,
+                                                        (1 + IMSI_LENGTH + config->identity_len));
+                                        else if (identity_format == EAP_IDENTITY_IMSI_3GPP_REALM)
+                                                os_memset(imsi_identity, 0,
+                                                        (1 + IMSI_LENGTH + os_strlen(realm_3gpp)));
+                                        else
+                                                os_memset(imsi_identity, 0, (1 + IMSI_LENGTH));
+
+                                        if (eap_proxy->eap_type == EAP_TYPE_SIM)
+                                                imsi_identity[0] = '1';
+                                        else if (eap_proxy->eap_type == EAP_TYPE_AKA)
+                                                imsi_identity[0] = '0';
+#ifdef CONFIG_EAP_PROXY_AKA_PRIME
+                                        else if (eap_proxy->eap_type == EAP_TYPE_AKA_PRIME)
+                                                imsi_identity[0] = '6';
+#endif /* CONFIG_EAP_PROXY_AKA_PRIME */
+                                        else
+                                                /* Default value is set as SIM */
+                                                imsi_identity[0] = '1';
+
+                                        /* copying IMSI value */
+                                        os_memcpy(imsi_identity + 1 , imsi , imsi_len_g);
+
+                                        if (config->identity_len > 1 && NULL != identity) {
+                                                /* copying realm tag */
+                                                os_memcpy(imsi_identity + 1 + imsi_len_g , identity,
+                                                        config->identity_len);
+                                                imsi_id_len = imsi_len_g + 1 + config->identity_len;
+                                                os_free(identity);
+                                                identity = NULL;
+                                        } else if(identity_format == EAP_IDENTITY_IMSI_3GPP_REALM) {
+                                                /* realm is not available so append it */
+                                                os_memcpy(imsi_identity + 1 + imsi_len_g,
+                                                        realm_3gpp, os_strlen(realm_3gpp));
+                                                imsi_id_len = imsi_len_g + 1 +
+                                                        os_strlen(realm_3gpp);
+                                        } else
+                                                /* IMSI RAW */
+                                                imsi_id_len = imsi_len_g + 1;
+                                }
+                        } else if (identity) {
+                                /* idx is non-zero implies username available */
+                                imsi_identity = identity;
+                                imsi_id_len = config->identity_len;
+                        }
+                }
+
+                if (identity_format == EAP_IDENTITY_IMSI_3GPP_REALM || mcc_idx) {
+
+                        if (0 == idx) {
+                        /* id = @wlan.mnc000.mcc000.<>.<> realm exist
+                                but need to insert mnc and mcc values */
+                                idx = imsi_len_g + 1;
+                        }
+
+                        if (imsi_identity != NULL) {
+                                /* mcc valus */
+                                imsi_identity[idx + 16] = imsi[0];
+                                imsi_identity[idx + 17] = imsi[1];
+                                imsi_identity[idx + 18] = imsi[2];
+                        }
+
+                        /* mnc valus */
+                        mnc_len = card_mnc_len;
+                        wpa_printf(MSG_ERROR, "eap_proxy: card mnc len %d\n", card_mnc_len);
+
+                        if ((mnc_len == 2) && (imsi_identity != NULL)) {
+                                imsi_identity[idx + 9]  = '0';
+                                imsi_identity[idx + 10] = imsi[3];
+                                imsi_identity[idx + 11] = imsi[4];
+                        } else if ((mnc_len == 3) && (imsi_identity != NULL)) {
+                                imsi_identity[idx + 9]  = imsi[3];
+                                imsi_identity[idx + 10] = imsi[4];
+                                imsi_identity[idx + 11] = imsi[5];
+                        }
+                        wpa_printf(MSG_ERROR, "eap_proxy:  Appending 3gpp realm\n ");
+                }
+                identity = imsi_identity;
+                identity_len = imsi_id_len;
+                eap_auth_start.user_id_valid = 1;
+        }
+
+        eap_auth_start.user_id_len = identity_len;
+
+        if(identity_len >= QMI_AUTH_EAP_IDENTITY_MAX_CHAR_V01)
+        {
+                wpa_printf(MSG_ERROR, "eap_proxy: Invalid User Identity length =%d",identity_len);
+                return FALSE;
+        }
+
+        if(identity)
+        {
+                memcpy(&eap_auth_start.user_id, identity, identity_len);
+                eap_auth_start.user_id_valid = 1;
+        }
+
+        wpa_printf(MSG_ERROR, "eap_proxy: eap auth user identity  - %20s length-%d\n ",
+                    eap_auth_start.user_id, eap_auth_start.user_id_len);
+
+        if ( (sim_num < 0) || (sim_num >= MAX_NO_OF_SIM_SUPPORTED)) {
+                wpa_printf(MSG_ERROR, "eap_proxy: SIM: Invalid SIM selected by "
+                            "User: Selected sim = %d\n", sim_num+1);
+                return FALSE;
+        }
+
+
+        eap_proxy->user_selected_sim = sim_num;
+        wpa_printf(MSG_ERROR, "eap_proxy: SIM selected by User: Selected sim = %d\n",
+                    eap_proxy->user_selected_sim+1);
+
+        memset(&sub_req_binding, 0, sizeof(auth_set_subscription_binding_req_msg_v01));
+        memset(&sub_resp_binding, 0, sizeof(auth_set_subscription_binding_resp_msg_v01));
+#ifdef CONFIG_EAP_PROXY_DUAL_SIM
+        if (sim_num == 0) {
+                sub_req_binding.bind_subs = AUTH_PRIMARY_SUBS_V01;
+                qmiRetCode = qmi_client_send_msg_sync(eap_proxy->qmi_auth_svc_client_ptr[sim_num],
+                                QMI_AUTH_SET_SUBSCRIPTION_BINDING_REQ_V01,
+                                                (void *) &sub_req_binding,
+                                                sizeof(auth_set_subscription_binding_req_msg_v01),
+                                                (void *) &sub_resp_binding,
+                                                sizeof(auth_set_subscription_binding_resp_msg_v01),
+                                                WPA_UIM_QMI_DEFAULT_TIMEOUT);
+
+                if ((QMI_NO_ERR != qmiRetCode ||
+                     sub_resp_binding.resp.result != QMI_RESULT_SUCCESS_V01 ) &&
+                    (QMI_ERR_OP_DEVICE_UNSUPPORTED_V01 != sub_resp_binding.resp.error)) {
+                        wpa_printf(MSG_ERROR, "QMI-ERROR Unable to get the qmi_auth_set_subscriptio"
+                                "n_binding for sim 1; error_ret=%d; error_code=%d\n", qmiRetCode,
+                                sub_resp_binding.resp.error);
+                        return FALSE;
+                }
+                wpa_printf (MSG_ERROR, "eap_proxy: Binded with PRIMARY Subscription\n");
+        } else if (sim_num == 1) {
+                sub_req_binding.bind_subs = AUTH_SECONDARY_SUBS_V01;
+                qmiRetCode = qmi_client_send_msg_sync(eap_proxy->qmi_auth_svc_client_ptr[sim_num],
+                                QMI_AUTH_SET_SUBSCRIPTION_BINDING_REQ_V01,
+                                                (void *) &sub_req_binding,
+                                                sizeof(auth_set_subscription_binding_req_msg_v01),
+                                                (void *) &sub_resp_binding,
+                                                sizeof(auth_set_subscription_binding_resp_msg_v01),
+                                                WPA_UIM_QMI_DEFAULT_TIMEOUT);
+
+                if (QMI_NO_ERR != qmiRetCode ||
+                    sub_resp_binding.resp.result != QMI_RESULT_SUCCESS_V01 ) {
+                        wpa_printf(MSG_ERROR, "QMI-ERROR Unable to get the qmi_auth_set_subscriptio"
+                                "n_binding for sim 2; error_ret=%d; error_code=%d\n", qmiRetCode,
+                                sub_resp_binding.resp.error);
+                        return FALSE;
+                }
+
+                wpa_printf (MSG_ERROR, "eap_proxy: Binded with SECONDARY Subscription\n");
+        } else {
+                wpa_printf(MSG_ERROR, "eap_proxy: Invalid SIM selected by User: "
+                        "Selected sim = %d\n", sim_num+1);
+                return FALSE;
+        }
+#endif
+        if (TRUE == eap_proxy->eap_auth_session_flag[sim_num]) {
+                if(eap_auth_end_eap_session(eap_proxy->qmi_auth_svc_client_ptr[sim_num]) < 0) {
+                        wpa_printf(MSG_ERROR, "eap_proxy: Unable to end the EAP session;"
+                                                " sim_num%d;", sim_num);
+                        }
+                        eap_proxy->eap_auth_session_flag[sim_num] = FALSE;
+        }
+
+        if (FALSE == eap_proxy->eap_auth_session_flag[sim_num]) {
+                        wpa_printf(MSG_ERROR, "eap_proxy: eap_auth_start values\n");
+                        wpa_printf(MSG_ERROR, "eap_proxy: eap_auth_start.eap_method_mask = %d\n",
+                                eap_auth_start.eap_method_mask);
+                        wpa_printf(MSG_ERROR, "eap_proxy: eap_auth_start.user_id_len = %d\n",
+                                eap_auth_start.user_id_len);
+                        wpa_printf(MSG_ERROR, "eap_proxy: eap_auth_start.eap_meta_id_len = %d\n",
+                                eap_auth_start.eap_meta_identity_len);
+                        wpa_printf(MSG_ERROR, "eap_auth_start.eap_sim_aka_algo = %d\n",
+                                eap_auth_start.eap_sim_aka_algo);
+        qmiRetCode = qmi_client_send_msg_sync(eap_proxy->qmi_auth_svc_client_ptr[sim_num],
+                                                QMI_AUTH_START_EAP_SESSION_REQ_V01,
+                                                (void *) &eap_auth_start,
+                                                sizeof(auth_start_eap_session_req_msg_v01),
+                                                (void *) &eap_auth_start_resp,
+                                                sizeof(auth_start_eap_session_resp_msg_v01),
+                                                WPA_UIM_QMI_DEFAULT_TIMEOUT);
+        if (QMI_NO_ERR != qmiRetCode ||
+            eap_auth_start_resp.resp.result != QMI_RESULT_SUCCESS_V01) {
+                wpa_printf(MSG_ERROR, " QMI-ERROR Unable to start the EAP session;"
+                           " error_ret=%d; qmi_err=%d\n", qmiRetCode,
+                           eap_auth_start_resp.resp.error);
+                if(eap_auth_start.eap_method_mask == QMI_AUTH_EAP_METHOD_MASK_AKA_PRIME_V01 &&
+                   eap_auth_start_resp.resp.error == QMI_ERR_INVALID_ARG_V01)
+                        wpa_printf(MSG_ERROR, "QMI-ERROR AKA' not supported\n");
+
+                return FALSE;
+                }
+                eap_proxy->eap_auth_session_flag[sim_num] = TRUE;
+                eap_proxy->notification_code = 0;
+                eap_proxy->qmi_state = QMI_STATE_IDLE;
+                wpa_printf(MSG_ERROR, "eap_proxy: EAP session started"
+                           " error_ret=%d; Resp=%d\n", qmiRetCode,
+                            eap_auth_start_resp.resp.error);
+        }
+
+        return TRUE;
+}
+
+
+
+#ifdef CONFIG_CTRL_IFACE
+
+/**
+ * eap_proxyl_sm_get_status - Get EAP state machine status
+ * @sm: Pointer to EAP state machine allocated with eap_sm_init()
+ * @buf: Buffer for status information
+ * @buflen: Maximum buffer length
+ * @verbose: Whether to include verbose status information
+ * Returns: Number of bytes written to buf.
+ *
+ * Query EAP state machine for status information. This function fills in a
+ * text area with current status information from the EAPOL state machine. If
+ * the buffer (buf) is not large enough, status information will be truncated
+ * to fit the buffer.
+ */
+int eap_proxy_sm_get_status(struct eap_proxy_sm *sm, char *buf, size_t buflen,
+                            int verbose)
+{
+        int len, ret;
+
+        if (sm == NULL)
+                return 0;
+
+        len = os_snprintf(buf, buflen, "eap_proxy: EAP state=%s\n",
+                          eap_proxy_sm_state_txt(sm->proxy_state));
+        if (len < 0 || (size_t)len >= buflen)
+                return 0;
+
+        if (sm->eap_type != EAP_TYPE_NONE) {
+                char name[8];
+
+                if (sm->eap_type == EAP_TYPE_SIM)
+                        os_strlcpy(name, "SIM", 4);
+                else if (sm->eap_type == EAP_TYPE_AKA)
+                        os_strlcpy(name, "AKA", 4);
+                else if (sm->eap_type == EAP_TYPE_AKA_PRIME)
+                        os_strlcpy(name, "AKA'", 5);
+                else
+                        os_strlcpy(name, "Unknown", 8);
+
+                ret = os_snprintf(buf + len, buflen - len,
+                                "selectedMethod=%d (EAP-%s)\n",
+                                        sm->eap_type, name);
+                if (ret < 0 || (size_t)ret >= buflen - len)
+                        return len;
+                len += ret;
+        }
+
+        return len;
+}
+
+
+static const char *eap_proxy_sm_state_txt(int state)
+{
+        switch (state) {
+        case EAP_PROXY_INITIALIZE:
+                return "INITIALIZE";
+        case EAP_PROXY_DISABLED:
+                return "DISABLED";
+        case EAP_PROXY_IDLE:
+                return "IDLE";
+        case EAP_PROXY_RECEIVED:
+                return "RECEIVED";
+        case EAP_PROXY_GET_METHOD:
+                return "GET_METHOD";
+        case EAP_PROXY_METHOD:
+                return "METHOD";
+        case EAP_PROXY_SEND_RESPONSE:
+                return "SEND_RESPONSE";
+        case EAP_PROXY_DISCARD:
+                return "DISCARD";
+        case EAP_PROXY_IDENTITY:
+                return "IDENTITY";
+        case EAP_PROXY_NOTIFICATION:
+                return "NOTIFICATION";
+        case EAP_PROXY_RETRANSMIT:
+                return "RETRANSMIT";
+        case EAP_PROXY_AUTH_SUCCESS:
+                return "SUCCESS";
+        case EAP_PROXY_AUTH_FAILURE:
+                return "FAILURE";
+        default:
+                return "UNKNOWN";
+        }
+}
+#endif /* CONFIG_CTRL_IFACE */
+
+
+/**
+ * eap_proxy_get_mcc_mnc - Get MCC/MNC
+ * @imsi_buf: Buffer for returning IMSI
+ * @imsi_len: Buffer for returning IMSI length
+ * Returns: MNC length (2 or 3) or -1 on error
+ */
+int eap_proxy_get_imsi(struct eap_proxy_sm *eap_proxy, char *imsi_buf,
+                        size_t *imsi_len)
+{
+#ifdef SIM_AKA_IDENTITY_IMSI
+        int mnc_len;
+        int sim_num = eap_proxy->user_selected_sim;
+
+        if ((eap_proxy->proxy_state == EAP_PROXY_DISABLED) ||
+            (eap_proxy->proxy_state == EAP_PROXY_INITIALIZE)) {
+                wpa_printf(MSG_ERROR, "eap_proxy:%s: Not initialized\n", __func__);
+                return FALSE;
+        }
+        if (!wpa_qmi_read_card_status(sim_num, eap_proxy->wpa_uim)) {
+        wpa_printf(MSG_INFO, "eap_proxy: Card not ready");
+                return -1;
+        }
+
+        if (!wpa_qmi_read_card_imsi(sim_num, eap_proxy->wpa_uim) || imsi == NULL) {
+                wpa_printf(MSG_INFO, "eap_proxy: Failed to read card IMSI");
+                return -1;
+        }
+
+        *imsi_len = os_strlen(imsi);
+        os_memcpy(imsi_buf, imsi, *imsi_len + 1);
+
+        mnc_len = card_mnc_len;
+        if (mnc_len < 2 || mnc_len > 3)
+                mnc_len = 3; /* Default to 3 if MNC length is unknown */
+
+        os_free(imsi);
+        imsi = NULL;
+
+        return mnc_len;
+#else /* SIM_AKA_IDENTITY_IMSI */
+        return -1;
+#endif /* SIM_AKA_IDENTITY_IMSI */
+}
+
+int eap_proxy_notify_config(struct eap_proxy_sm *eap_proxy,
+                            struct eap_peer_config *config)
+{
+        int ret_val;
+
+        wpa_printf(MSG_ERROR, "eap_proxy: eap_proxy_notify_config\n");
+        if (!eap_proxy) {
+                wpa_printf(MSG_ERROR, "eap_proxy: is NULL");
+                return FALSE;
+        }
+
+        if ((eap_proxy->proxy_state == EAP_PROXY_DISABLED) ||
+            (eap_proxy->proxy_state == EAP_PROXY_INITIALIZE)) {
+                wpa_printf(MSG_ERROR, "eap_proxy: Not initialized\n");
+                return FALSE;
+        }
+
+        if ( config && eap_proxy_allowed_method(config, EAP_VENDOR_IETF,
+                        EAP_TYPE_SIM)) {
+                eap_proxy->eap_type =  EAP_TYPE_SIM;
+                ret_val = TRUE;
+        } else if ( config && eap_proxy_allowed_method(config, EAP_VENDOR_IETF,
+                                EAP_TYPE_AKA)) {
+                eap_proxy->eap_type =  EAP_TYPE_AKA;
+                ret_val = TRUE;
+        } else if ( config && eap_proxy_allowed_method(config, EAP_VENDOR_IETF,
+                                EAP_TYPE_AKA_PRIME)) {
+                eap_proxy->eap_type =  EAP_TYPE_AKA_PRIME;
+                ret_val = TRUE;
+        } else
+                ret_val = FALSE;
+
+        return ret_val;
+}
+
+int eap_proxy_allowed_method(struct eap_peer_config *config, int vendor,
+                              u32 method)
+{
+        int i;
+        struct eap_method_type *m;
+
+        wpa_printf(MSG_ERROR, "eap_proxy: eap_proxy_allowed_method");
+        if (config == NULL || config->eap_methods == NULL)
+                return -1;
+
+        m = config->eap_methods;
+        for (i = 0; m[i].vendor != EAP_VENDOR_IETF ||
+                     m[i].method != EAP_TYPE_NONE; i++) {
+                if (m[i].vendor == vendor && m[i].method == method)
+                        return 1;
+        }
+        return 0;
+}
+
+#endif  /* CONFIG_EAP_PROXY */
diff --git a/src/eap_peer/eap_proxy_qmi_oc.h b/src/eap_peer/eap_proxy_qmi_oc.h
new file mode 100644
index 0000000..f597afd
--- /dev/null
+++ b/src/eap_peer/eap_proxy_qmi_oc.h
@@ -0,0 +1,140 @@
+/*--------------------------------------------------------------------------
+Copyright (c) 2013, The Linux Foundation. All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+    * Redistributions of source code must retain the above copyright
+      notice, this list of conditions and the following disclaimer.
+    * Redistributions in binary form must reproduce the above
+      copyright notice, this list of conditions and the following
+      disclaimer in the documentation and/or other materials provided
+      with the distribution.
+    * Neither the name of The Linux Foundation nor the names of its
+      contributors may be used to endorse or promote products derived
+      from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+--------------------------------------------------------------------------*/
+
+#ifndef EAP_PROXY_QMI_H
+#define EAP_PROXY_QMI_H
+
+
+#include "eap_i.h"
+#include "eap_config.h"
+#include "eloop.h"
+#include "eapol_supp/eapol_supp_sm.h"
+#include "user_identity_module_v01.h"
+
+/*msec Response Timeout*/
+#define QMI_RESP_TIME_OUT 2000
+#define EAP_PROXY_KEYING_DATA_LEN 64
+
+#ifdef CONFIG_EAP_PROXY_DUAL_SIM
+#define MAX_NO_OF_SIM_SUPPORTED 2
+#else
+#define MAX_NO_OF_SIM_SUPPORTED 1
+#endif /* CONFIG_EAP_PROXY_DUAL_SIM */
+
+typedef enum {
+        QMI_STATE_IDLE = 0x00,
+        QMI_STATE_RESP_PENDING  = 0x01,
+        QMI_STATE_RESP_RECEIVED = 0x02,
+        QMI_STATE_RESP_TIME_OUT = 0x03
+} qmi_state_e;
+
+typedef enum {
+        EAP_PROXY_QMI_SRVC_NO_RESULT,
+        EAP_PROXY_QMI_SRVC_SUCCESS,
+        EAP_PROXY_QMI_SRVC_FAILURE
+} eap_proxy_qmi_srv_result;
+
+/* should match the EAP_state  of eap_i.h */
+typedef enum {
+        EAP_PROXY_INITIALIZE, EAP_PROXY_DISABLED, EAP_PROXY_IDLE, EAP_PROXY_RECEIVED,
+        EAP_PROXY_GET_METHOD, EAP_PROXY_METHOD, EAP_PROXY_SEND_RESPONSE,
+        EAP_PROXY_DISCARD, EAP_PROXY_IDENTITY, EAP_PROXY_NOTIFICATION,
+        EAP_PROXY_RETRANSMIT,
+        EAP_PROXY_AUTH_SUCCESS,  EAP_PROXY_AUTH_FAILURE
+} eap_proxy_state;
+
+
+enum eap_proxy_status {
+        EAP_PROXY_FAILURE = 0x00,
+        EAP_PROXY_SUCCESS
+};
+
+typedef enum {
+        EAP_IDENTITY_ANNONYMOUS = 0x00,
+        EAP_IDENTITY_IMSI_RAW  = 0x02,
+        EAP_IDENTITY_IMSI_3GPP_REALM = 0x03,
+        EAP_IDENTITY_IMSI_REALM = 0x04,
+        EAP_IDENTITY_CFG_RAW = 0x05,
+        EAP_IDENTITY_CFG_3GPP_REALM = 0x06,
+        EAP_IDENTITY_CFG_REALM = 0x07,
+} eap_identity_format_e;
+
+typedef union
+{
+        struct
+        {
+                void *resp_data; /* Pointer to the Response Packet*/
+                unsigned long length;     /*Length of the Response Packet*/
+        }eap_send_pkt_resp;
+
+}qmi_eap_sync_rsp_data_type;
+
+typedef struct {
+        uim_card_state_enum_v01                      card_state;
+        uim_card_error_code_enum_v01                 card_error_code;
+        u8                                           app_state;
+        u8                                           app_type;
+} wpa_uim_card_info_type;
+
+typedef struct {
+        int                                   card_ready_idx;
+        wpa_uim_card_info_type                card_info[QMI_UIM_CARDS_MAX_V01];
+        qmi_client_type                       qmi_uim_svc_client_ptr;
+        int                                   qmi_msg_lib_handle;
+} wpa_uim_struct_type;
+
+
+struct eap_proxy_sm {
+        qmi_client_type qmi_auth_svc_client_ptr[MAX_NO_OF_SIM_SUPPORTED];
+        qmi_state_e qmi_state;
+        eap_proxy_qmi_srv_result srvc_result;
+        qmi_eap_sync_rsp_data_type qmi_resp_data;
+        eap_proxy_state  proxy_state;
+        Boolean iskey_valid;
+        u8 *key;
+        Boolean is_state_changed;
+        void *ctx;
+        void *msg_ctx;
+        struct eapol_callbacks *eapol_cb;
+        u8 *eapReqData;
+        size_t eapReqDataLen;
+        Boolean isEap;
+        int eap_type;
+        int user_selected_sim;
+        int eap_auth_session_flag[MAX_NO_OF_SIM_SUPPORTED];
+        int notification_code;
+        pthread_t thread_id;
+        wpa_uim_struct_type   wpa_uim[MAX_NO_OF_SIM_SUPPORTED];
+        Boolean qmi_uim_svc_client_initialized[MAX_NO_OF_SIM_SUPPORTED];
+};
+
+int eap_proxy_allowed_method(struct eap_peer_config *config, int vendor,
+                              u32 method);
+
+#endif /* EAP_PROXY_QMI_H */
diff --git a/src/eap_peer/eap_sim.c b/src/eap_peer/eap_sim.c
index 25f592c..c0896aa 100644
--- a/src/eap_peer/eap_sim.c
+++ b/src/eap_peer/eap_sim.c
@@ -47,6 +47,7 @@
 	} state;
 	int result_ind, use_result_ind;
 	int use_pseudonym;
+	int error_code;
 };
 
 
@@ -94,6 +95,9 @@
 		return NULL;
 	}
 
+	/* Zero is a valid error code, so we need to initialize */
+	data->error_code = NO_EAP_METHOD_ERROR;
+
 	data->min_num_chal = 2;
 	if (config && config->phase1) {
 		char *pos = os_strstr(config->phase1, "sim_min_num_chal=");
@@ -767,8 +771,17 @@
 	} else if (data->pseudonym) {
 		identity = data->pseudonym;
 		identity_len = data->pseudonym_len;
-	} else
-		identity = eap_get_config_identity(sm, &identity_len);
+	} else {
+		struct eap_peer_config *config;
+
+		config = eap_get_config(sm);
+		if (config && config->imsi_identity) {
+			identity = config->imsi_identity;
+			identity_len = config->imsi_identity_len;
+		} else {
+			identity = eap_get_config_identity(sm, &identity_len);
+		}
+	}
 	wpa_hexdump_ascii(MSG_DEBUG, "EAP-SIM: Selected identity for MK "
 			  "derivation", identity, identity_len);
 	eap_sim_derive_mk(identity, identity_len, data->nonce_mt,
@@ -911,6 +924,7 @@
 
 	eap_sim_report_notification(sm->msg_ctx, attr->notification, 0);
 	if (attr->notification >= 0 && attr->notification < 32768) {
+		data->error_code = attr->notification;
 		eap_sim_state(data, FAILURE);
 	} else if (attr->notification == EAP_SIM_SUCCESS &&
 		   data->state == RESULT_SUCCESS)
@@ -1234,6 +1248,20 @@
 	return key;
 }
 
+static int eap_sim_get_error_code(void *priv)
+{
+	struct eap_sim_data *data = priv;
+
+	if (!data)
+		return NO_EAP_METHOD_ERROR;
+
+	int current_data_error = data->error_code;
+
+	/* Now reset for next transaction */
+	data->error_code = NO_EAP_METHOD_ERROR;
+
+	return current_data_error;
+}
 
 int eap_peer_sim_register(void)
 {
@@ -1255,6 +1283,7 @@
 	eap->init_for_reauth = eap_sim_init_for_reauth;
 	eap->get_identity = eap_sim_get_identity;
 	eap->get_emsk = eap_sim_get_emsk;
+	eap->get_error_code = eap_sim_get_error_code;
 
 	return eap_peer_method_register(eap);
 }
diff --git a/src/eapol_supp/eapol_supp_sm.c b/src/eapol_supp/eapol_supp_sm.c
index 8e4f0e4..cb463ef 100644
--- a/src/eapol_supp/eapol_supp_sm.c
+++ b/src/eapol_supp/eapol_supp_sm.c
@@ -2014,6 +2014,13 @@
 		sm->ctx->status_cb(sm->ctx->ctx, status, parameter);
 }
 
+static void eapol_sm_notify_eap_error(void *ctx, int error_code)
+{
+	struct eapol_sm *sm = ctx;
+
+	if (sm->ctx->eap_error_cb)
+		sm->ctx->eap_error_cb(sm->ctx->ctx, error_code);
+}
 
 #ifdef CONFIG_EAP_PROXY
 
@@ -2062,6 +2069,7 @@
 	eapol_sm_eap_param_needed,
 	eapol_sm_notify_cert,
 	eapol_sm_notify_status,
+	eapol_sm_notify_eap_error,
 #ifdef CONFIG_EAP_PROXY
 	eapol_sm_eap_proxy_cb,
 	eapol_sm_eap_proxy_notify_sim_status,
diff --git a/src/eapol_supp/eapol_supp_sm.h b/src/eapol_supp/eapol_supp_sm.h
index a25c799..74f40bb 100644
--- a/src/eapol_supp/eapol_supp_sm.h
+++ b/src/eapol_supp/eapol_supp_sm.h
@@ -271,6 +271,13 @@
 	void (*status_cb)(void *ctx, const char *status,
 			  const char *parameter);
 
+	/**
+	 * eap_error_cb - Notification of EAP method error
+	 * @ctx: Callback context (ctx)
+	 * @error_code: EAP method error code
+	 */
+	void (*eap_error_cb)(void *ctx, int error_code);
+
 #ifdef CONFIG_EAP_PROXY
 	/**
 	 * eap_proxy_cb - Callback signifying any updates from eap_proxy
diff --git a/src/rsn_supp/wpa.c b/src/rsn_supp/wpa.c
index 15b0e60..ff4a6ed 100644
--- a/src/rsn_supp/wpa.c
+++ b/src/rsn_supp/wpa.c
@@ -505,7 +505,7 @@
 
 	os_memcpy(reply->key_nonce, nonce, WPA_NONCE_LEN);
 
-	wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, "WPA: Sending EAPOL-Key 2/4");
+	wpa_dbg(sm->ctx->msg_ctx, MSG_INFO, "WPA: Sending EAPOL-Key 2/4");
 	return wpa_eapol_key_send(sm, ptk, ver, dst, ETH_P_EAPOL, rbuf, rlen,
 				  key_mic);
 }
@@ -545,7 +545,7 @@
 	}
 
 	wpa_sm_set_state(sm, WPA_4WAY_HANDSHAKE);
-	wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, "WPA: RX message 1 of 4-Way "
+	wpa_dbg(sm->ctx->msg_ctx, MSG_INFO, "WPA: RX message 1 of 4-Way "
 		"Handshake from " MACSTR " (ver=%d)", MAC2STR(src_addr), ver);
 
 	os_memset(&ie, 0, sizeof(ie));
@@ -1326,7 +1326,7 @@
 	key_mic = (u8 *) (reply + 1);
 	WPA_PUT_BE16(key_mic + mic_len, 0);
 
-	wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, "WPA: Sending EAPOL-Key 4/4");
+	wpa_dbg(sm->ctx->msg_ctx, MSG_INFO, "WPA: Sending EAPOL-Key 4/4");
 	return wpa_eapol_key_send(sm, ptk, ver, dst, ETH_P_EAPOL, rbuf, rlen,
 				  key_mic);
 }
@@ -1341,7 +1341,7 @@
 	struct wpa_eapol_ie_parse ie;
 
 	wpa_sm_set_state(sm, WPA_4WAY_HANDSHAKE);
-	wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, "WPA: RX message 3 of 4-Way "
+	wpa_dbg(sm->ctx->msg_ctx, MSG_INFO, "WPA: RX message 3 of 4-Way "
 		"Handshake from " MACSTR " (ver=%d)", MAC2STR(sm->bssid), ver);
 
 	key_info = WPA_GET_BE16(key->key_info);
diff --git a/src/utils/os_unix.c b/src/utils/os_unix.c
index 3f6388d..381846a 100644
--- a/src/utils/os_unix.c
+++ b/src/utils/os_unix.c
@@ -341,22 +341,28 @@
 	gid_t groups[] = { ANDROID_SETGROUPS_OVERRIDE };
 
 	if (!gid_wifi || !uid_wifi) return -1;
+	setgroups(ARRAY_SIZE(groups), groups);
 #else /* ANDROID_SETGROUPS_OVERRIDE */
-	gid_t groups[3];
+	gid_t groups[4];
+	int group_idx = 0;
 
 	if (!gid_wifi || !uid_wifi) return -1;
-	groups[0] = gid_wifi;
+	groups[group_idx] = gid_wifi;
 
 	grp = getgrnam("inet");
-	groups[1] = grp ? grp->gr_gid : 0;
-	if (!groups[1]) return -1;
+	groups[++group_idx] = grp ? grp->gr_gid : 0;
+	if (!groups[group_idx]) return -1;
 
 	grp = getgrnam("keystore");
-	groups[2] = grp ? grp->gr_gid : 0;
-	if (!groups[2]) return -1;
-#endif /* ANDROID_SETGROUPS_OVERRIDE */
+	groups[++group_idx] = grp ? grp->gr_gid : 0;
+	if (!groups[group_idx]) return -1;
 
-	setgroups(ARRAY_SIZE(groups), groups);
+	grp = getgrnam("log");
+	groups[++group_idx] = grp ? grp->gr_gid : 0;
+	if (!groups[group_idx]) group_idx--;
+
+	setgroups(group_idx + 1, groups);
+#endif /* ANDROID_SETGROUPS_OVERRIDE */
 
 	prctl(PR_SET_KEEPCAPS, 1, 0, 0, 0);
 
diff --git a/wpa_supplicant/Android.mk b/wpa_supplicant/Android.mk
index df27835..d57446c 100644
--- a/wpa_supplicant/Android.mk
+++ b/wpa_supplicant/Android.mk
@@ -65,11 +65,11 @@
 endif
 
 # Use Android specific directory for control interface sockets
-L_CFLAGS += -DCONFIG_CTRL_IFACE_CLIENT_DIR=\"/data/misc/wifi/sockets\"
-L_CFLAGS += -DCONFIG_CTRL_IFACE_DIR=\"/data/misc/wifi/sockets\"
+L_CFLAGS += -DCONFIG_CTRL_IFACE_CLIENT_DIR=\"/data/vendor/wifi/wpa/sockets\"
+L_CFLAGS += -DCONFIG_CTRL_IFACE_DIR=\"/data/vendor/wifi/wpa/sockets\"
 
 # Use Android specific directory for wpa_cli command completion history
-L_CFLAGS += -DCONFIG_WPA_CLI_HISTORY_DIR=\"/data/misc/wifi\"
+L_CFLAGS += -DCONFIG_WPA_CLI_HISTORY_DIR=\"/data/vendor/wifi/wpa\"
 
 # To force sizeof(enum) = 4
 ifeq ($(TARGET_ARCH),arm)
@@ -1723,6 +1723,7 @@
 endif
 ifeq ($(WPA_SUPPLICANT_USE_HIDL), y)
 LOCAL_SHARED_LIBRARIES += android.hardware.wifi.supplicant@1.0
+LOCAL_SHARED_LIBRARIES += android.hardware.wifi.supplicant@1.1
 LOCAL_SHARED_LIBRARIES += libhidlbase libhidltransport libhwbinder libutils libbase
 LOCAL_STATIC_LIBRARIES += libwpa_hidl
 endif
@@ -1773,7 +1774,7 @@
 LOCAL_CPPFLAGS := $(L_CPPFLAGS)
 LOCAL_CFLAGS := $(L_CFLAGS)
 LOCAL_C_INCLUDES := $(INCLUDES)
-HIDL_INTERFACE_VERSION = 1.0
+HIDL_INTERFACE_VERSION = 1.1
 LOCAL_SRC_FILES := \
     hidl/$(HIDL_INTERFACE_VERSION)/hidl.cpp \
     hidl/$(HIDL_INTERFACE_VERSION)/hidl_manager.cpp \
@@ -1784,11 +1785,11 @@
     hidl/$(HIDL_INTERFACE_VERSION)/sta_network.cpp \
     hidl/$(HIDL_INTERFACE_VERSION)/supplicant.cpp
 LOCAL_SHARED_LIBRARIES := \
-    android.hardware.wifi.supplicant@$(HIDL_INTERFACE_VERSION) \
+    android.hardware.wifi.supplicant@1.0 \
+    android.hardware.wifi.supplicant@1.1 \
     libbase \
     libhidlbase \
     libhidltransport \
-    libhwbinder \
     libutils \
     liblog
 LOCAL_EXPORT_C_INCLUDE_DIRS := \
diff --git a/wpa_supplicant/config.c b/wpa_supplicant/config.c
index a0d480e..a22434c 100644
--- a/wpa_supplicant/config.c
+++ b/wpa_supplicant/config.c
@@ -2154,6 +2154,7 @@
 	{ FUNC(eap) },
 	{ STR_LENe(identity) },
 	{ STR_LENe(anonymous_identity) },
+	{ STR_LENe(imsi_identity) },
 	{ FUNC_KEY(password) },
 	{ STRe(ca_cert) },
 	{ STRe(ca_path) },
@@ -2411,6 +2412,7 @@
 	os_free(eap->eap_methods);
 	bin_clear_free(eap->identity, eap->identity_len);
 	os_free(eap->anonymous_identity);
+	os_free(eap->imsi_identity);
 	bin_clear_free(eap->password, eap->password_len);
 	os_free(eap->ca_cert);
 	os_free(eap->ca_path);
diff --git a/wpa_supplicant/config_file.c b/wpa_supplicant/config_file.c
index 0d70850..1fd432d 100644
--- a/wpa_supplicant/config_file.c
+++ b/wpa_supplicant/config_file.c
@@ -761,6 +761,7 @@
 	write_eap(f, ssid);
 	STR(identity);
 	STR(anonymous_identity);
+	STR(imsi_identity);
 	STR(password);
 	STR(ca_cert);
 	STR(ca_path);
diff --git a/wpa_supplicant/config_winreg.c b/wpa_supplicant/config_winreg.c
index 24f496b..0ba1aa5 100644
--- a/wpa_supplicant/config_winreg.c
+++ b/wpa_supplicant/config_winreg.c
@@ -880,6 +880,7 @@
 	write_eap(netw, ssid);
 	STR(identity);
 	STR(anonymous_identity);
+	STR(imsi_identity);
 	STR(password);
 	STR(ca_cert);
 	STR(ca_path);
diff --git a/wpa_supplicant/eap_proxy_qmi_oc.mak b/wpa_supplicant/eap_proxy_qmi_oc.mak
new file mode 100644
index 0000000..0a046f6
--- /dev/null
+++ b/wpa_supplicant/eap_proxy_qmi_oc.mak
@@ -0,0 +1,19 @@
+CFLAGS += -DSIM_AKA_IDENTITY_IMSI
+CFLAGS += -DSIM_AKA_IMSI_RAW_ENABLED
+
+CFLAGS += $(shell $(PKG_CONFIG) --cflags qmi qmi-framework)
+
+LIBS += $(shell $(PKG_CONFIG) --libs qmi qmi-framework) -lpthread
+
+# EAP-AKA' (enable CONFIG_PCSC, if EAP-AKA' is used).
+# This requires CONFIG_EAP_AKA to be enabled, too.
+# This is supported only in B Family devices.
+CONFIG_EAP_AKA_PRIME=y
+
+ifdef CONFIG_EAP_PROXY_AKA_PRIME
+CFLAGS += -DCONFIG_EAP_PROXY_AKA_PRIME
+endif
+
+ifdef CONFIG_EAP_PROXY_DUAL_SIM
+CFLAGS += -DCONFIG_EAP_PROXY_DUAL_SIM
+endif
diff --git a/wpa_supplicant/eap_proxy_qmi_oc.mk b/wpa_supplicant/eap_proxy_qmi_oc.mk
new file mode 100644
index 0000000..fe0a4a9
--- /dev/null
+++ b/wpa_supplicant/eap_proxy_qmi_oc.mk
@@ -0,0 +1,37 @@
+
+LOCAL_PATH := $(call my-dir)
+
+ifeq ($(BOARD_HAS_QCOM_WLAN), true)
+L_CFLAGS += -DSIM_AKA_IDENTITY_IMSI
+#L_CFLAGS += -DSIM_AKA_IMSI_RAW_ENABLED
+
+ifdef CONFIG_EAP_PROXY_DUAL_SIM
+L_CFLAGS += -DCONFIG_EAP_PROXY_DUAL_SIM
+endif
+
+LIB_SHARED_EAP_PROXY := libqmi_cci libqmiservices libidl
+INCLUDES += $(TARGET_OUT_HEADERS)/qmi-framework/inc
+INCLUDES += $(TARGET_OUT_HEADERS)/qmi/inc
+INCLUDES += $(TARGET_OUT_HEADERS)/qmi/platform
+INCLUDES += $(TARGET_OUT_HEADERS)/qmi/core/lib/inc
+
+ifdef CONFIG_EAP_PROXY_MDM_DETECT
+L_CFLAGS += -DCONFIG_EAP_PROXY_MDM_DETECT
+INCLUDES += $(TARGET_OUT_HEADERS)/libmdmdetect/inc
+LIB_SHARED_EAP_PROXY += libmdmdetect
+endif
+
+# EAP-AKA' (enable CONFIG_PCSC, if EAP-AKA' is used).
+# This requires CONFIG_EAP_AKA to be enabled, too.
+# This is supported only in B Family devices.
+ifdef CONFIG_EAP_PROXY_AKA_PRIME
+L_CFLAGS += -DCONFIG_EAP_PROXY_AKA_PRIME
+endif
+
+ifdef CONFIG_EAP_PROXY_MSM8994_TARGET
+L_CFLAGS += -DCONFIG_EAP_PROXY_MSM8994_TARGET
+endif
+
+#ANDROID_SETGROUPS_OVERRIDE := AID_RADIO AID_WIFI AID_KEYSTORE AID_DIAG AID_INET AID_QCOM_DIAG AID_NET_RAW
+L_CFLAGS += -DANDROID_SETGROUPS_OVERRIDE=1001,1010,1017,2002,1003,3009,3004
+endif
diff --git a/wpa_supplicant/hidl/1.0/hidl.cpp b/wpa_supplicant/hidl/1.0/hidl.cpp
index ab2043d..ce8a459 100644
--- a/wpa_supplicant/hidl/1.0/hidl.cpp
+++ b/wpa_supplicant/hidl/1.0/hidl.cpp
@@ -21,13 +21,14 @@
 }
 
 using android::hardware::configureRpcThreadpool;
-using android::hardware::IPCThreadState;
+using android::hardware::setupTransportPolling;
+using android::hardware::handleTransportPoll;
 using android::hardware::wifi::supplicant::V1_0::implementation::HidlManager;
 
 void wpas_hidl_sock_handler(
-    int /* sock */, void * /* eloop_ctx */, void * /* sock_ctx */)
+    int sock, void * /* eloop_ctx */, void * /* sock_ctx */)
 {
-	IPCThreadState::self()->handlePolledCommands();
+	handleTransportPoll(sock);
 }
 
 struct wpas_hidl_priv *wpas_hidl_init(struct wpa_global *global)
@@ -43,7 +44,7 @@
 	wpa_printf(MSG_DEBUG, "Initing hidl control");
 
 	configureRpcThreadpool(1, true /* callerWillJoin */);
-	IPCThreadState::self()->setupPolling(&priv->hidl_fd);
+	priv->hidl_fd = setupTransportPolling();
 	if (priv->hidl_fd < 0)
 		goto err;
 
@@ -76,7 +77,6 @@
 
 	HidlManager::destroyInstance();
 	eloop_unregister_read_sock(priv->hidl_fd);
-	IPCThreadState::shutdown();
 	os_free(priv);
 }
 
diff --git a/wpa_supplicant/hidl/1.0/p2p_iface.cpp b/wpa_supplicant/hidl/1.0/p2p_iface.cpp
index ab4014d..7a94a31 100644
--- a/wpa_supplicant/hidl/1.0/p2p_iface.cpp
+++ b/wpa_supplicant/hidl/1.0/p2p_iface.cpp
@@ -697,11 +697,13 @@
 		wps_method = WPS_PIN_KEYPAD;
 		break;
 	}
+	int vht = wpa_s->conf->p2p_go_vht;
+	int ht40 = wpa_s->conf->p2p_go_ht40 || vht;
 	const char* pin = pre_selected_pin.length() > 0 ? pre_selected_pin.data() : nullptr;
 	int new_pin = wpas_p2p_connect(
 	    wpa_s, peer_address.data(), pin, wps_method,
 	    persistent, false, join_existing_group, false, go_intent_signed, 0, 0, -1,
-	    false, false, false, VHT_CHANWIDTH_USE_HT, nullptr, 0);
+	    false, ht40, vht, VHT_CHANWIDTH_USE_HT, nullptr, 0);
 	if (new_pin < 0) {
 		return {{SupplicantStatusCode::FAILURE_UNKNOWN, ""}, {}};
 	}
diff --git a/wpa_supplicant/hidl/1.0/sta_network.cpp b/wpa_supplicant/hidl/1.0/sta_network.cpp
index 72185b3..f471941 100644
--- a/wpa_supplicant/hidl/1.0/sta_network.cpp
+++ b/wpa_supplicant/hidl/1.0/sta_network.cpp
@@ -1519,7 +1519,8 @@
 	enum wpa_ctrl_req_type rtype = WPA_CTRL_REQ_SIM;
 	struct wpa_supplicant *wpa_s = retrieveIfacePtr();
 	if (wpa_supplicant_ctrl_rsp_handle(
-		wpa_s, wpa_ssid, rtype, ctrl_rsp_param.c_str())) {
+		wpa_s, wpa_ssid, rtype, ctrl_rsp_param.data(),
+                ctrl_rsp_param.size())) {
 		return {SupplicantStatusCode::FAILURE_UNKNOWN, ""};
 	}
 	eapol_sm_notify_ctrl_response(wpa_s->eapol);
@@ -1535,7 +1536,8 @@
 	struct wpa_supplicant *wpa_s = retrieveIfacePtr();
 	enum wpa_ctrl_req_type rtype = WPA_CTRL_REQ_SIM;
 	if (wpa_supplicant_ctrl_rsp_handle(
-		wpa_s, wpa_ssid, rtype, kNetworkEapSimGsmAuthFailure)) {
+		wpa_s, wpa_ssid, rtype, kNetworkEapSimGsmAuthFailure,
+                strlen(kNetworkEapSimGsmAuthFailure))) {
 		return {SupplicantStatusCode::FAILURE_UNKNOWN, ""};
 	}
 	eapol_sm_notify_ctrl_response(wpa_s->eapol);
@@ -1568,7 +1570,8 @@
 	enum wpa_ctrl_req_type rtype = WPA_CTRL_REQ_SIM;
 	struct wpa_supplicant *wpa_s = retrieveIfacePtr();
 	if (wpa_supplicant_ctrl_rsp_handle(
-		wpa_s, wpa_ssid, rtype, ctrl_rsp_param.c_str())) {
+		wpa_s, wpa_ssid, rtype, ctrl_rsp_param.data(),
+                ctrl_rsp_param.size())) {
 		return {SupplicantStatusCode::FAILURE_UNKNOWN, ""};
 	}
 	eapol_sm_notify_ctrl_response(wpa_s->eapol);
@@ -1592,7 +1595,8 @@
 	enum wpa_ctrl_req_type rtype = WPA_CTRL_REQ_SIM;
 	struct wpa_supplicant *wpa_s = retrieveIfacePtr();
 	if (wpa_supplicant_ctrl_rsp_handle(
-		wpa_s, wpa_ssid, rtype, ctrl_rsp_param.c_str())) {
+		wpa_s, wpa_ssid, rtype, ctrl_rsp_param.data(),
+                ctrl_rsp_param.size())) {
 		return {SupplicantStatusCode::FAILURE_UNKNOWN, ""};
 	}
 	eapol_sm_notify_ctrl_response(wpa_s->eapol);
@@ -1608,7 +1612,8 @@
 	struct wpa_supplicant *wpa_s = retrieveIfacePtr();
 	enum wpa_ctrl_req_type rtype = WPA_CTRL_REQ_SIM;
 	if (wpa_supplicant_ctrl_rsp_handle(
-		wpa_s, wpa_ssid, rtype, kNetworkEapSimUmtsAuthFailure)) {
+		wpa_s, wpa_ssid, rtype, kNetworkEapSimUmtsAuthFailure,
+                strlen(kNetworkEapSimUmtsAuthFailure))) {
 		return {SupplicantStatusCode::FAILURE_UNKNOWN, ""};
 	}
 	eapol_sm_notify_ctrl_response(wpa_s->eapol);
@@ -1623,7 +1628,8 @@
 	enum wpa_ctrl_req_type rtype = WPA_CTRL_REQ_EAP_IDENTITY;
 	struct wpa_supplicant *wpa_s = retrieveIfacePtr();
 	if (wpa_supplicant_ctrl_rsp_handle(
-		wpa_s, wpa_ssid, rtype, ctrl_rsp_param.c_str())) {
+		wpa_s, wpa_ssid, rtype,  ctrl_rsp_param.data(),
+                ctrl_rsp_param.size())) {
 		return {SupplicantStatusCode::FAILURE_UNKNOWN, ""};
 	}
 	eapol_sm_notify_ctrl_response(wpa_s->eapol);
diff --git a/wpa_supplicant/hidl/1.1/hidl.cpp b/wpa_supplicant/hidl/1.1/hidl.cpp
new file mode 100644
index 0000000..95194af
--- /dev/null
+++ b/wpa_supplicant/hidl/1.1/hidl.cpp
@@ -0,0 +1,645 @@
+/*
+ * 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 <hwbinder/IPCThreadState.h>
+
+#include <hidl/HidlTransportSupport.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"
+}
+
+using android::hardware::configureRpcThreadpool;
+using android::hardware::setupTransportPolling;
+using android::hardware::handleTransportPoll;
+using android::hardware::wifi::supplicant::V1_1::implementation::HidlManager;
+
+void wpas_hidl_sock_handler(
+    int sock, void * /* eloop_ctx */, void * /* sock_ctx */)
+{
+	handleTransportPoll(sock);
+}
+
+struct wpas_hidl_priv *wpas_hidl_init(struct wpa_global *global)
+{
+	struct wpas_hidl_priv *priv;
+	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");
+
+	configureRpcThreadpool(1, true /* callerWillJoin */);
+	priv->hidl_fd = setupTransportPolling();
+	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 = 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");
+
+	HidlManager::destroyInstance();
+	eloop_unregister_read_sock(priv->hidl_fd);
+	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);
+
+	HidlManager *hidl_manager = 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);
+
+	HidlManager *hidl_manager = 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);
+
+	HidlManager *hidl_manager = 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);
+
+	HidlManager *hidl_manager = 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);
+
+	HidlManager *hidl_manager = 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);
+
+	HidlManager *hidl_manager = HidlManager::getInstance();
+	if (!hidl_manager)
+		return 1;
+
+	return hidl_manager->notifyNetworkRequest(
+	    wpa_s, ssid, rtype, default_txt);
+}
+
+void wpas_hidl_notify_anqp_query_done(
+    struct wpa_supplicant *wpa_s, const u8 *bssid, const char *result,
+    const struct wpa_bss_anqp *anqp)
+{
+	if (!wpa_s || !wpa_s->global->hidl || !bssid || !result || !anqp)
+		return;
+
+	wpa_printf(
+	    MSG_DEBUG,
+	    "Notifying ANQP query done to hidl control: " MACSTR "result: %s",
+	    MAC2STR(bssid), result);
+
+	HidlManager *hidl_manager = HidlManager::getInstance();
+	if (!hidl_manager)
+		return;
+
+	hidl_manager->notifyAnqpQueryDone(wpa_s, bssid, result, anqp);
+}
+
+void wpas_hidl_notify_hs20_icon_query_done(
+    struct wpa_supplicant *wpa_s, const u8 *bssid, const char *file_name,
+    const u8 *image, u32 image_length)
+{
+	if (!wpa_s || !wpa_s->global->hidl || !bssid || !file_name || !image)
+		return;
+
+	wpa_printf(
+	    MSG_DEBUG, "Notifying HS20 icon query done to hidl control: " MACSTR
+		       "file_name: %s",
+	    MAC2STR(bssid), file_name);
+
+	HidlManager *hidl_manager = HidlManager::getInstance();
+	if (!hidl_manager)
+		return;
+
+	hidl_manager->notifyHs20IconQueryDone(
+	    wpa_s, bssid, file_name, image, image_length);
+}
+
+void wpas_hidl_notify_hs20_rx_subscription_remediation(
+    struct wpa_supplicant *wpa_s, const char *url, u8 osu_method)
+{
+	if (!wpa_s || !wpa_s->global->hidl || !url)
+		return;
+
+	wpa_printf(
+	    MSG_DEBUG,
+	    "Notifying HS20 subscription remediation rx to hidl control: %s",
+	    url);
+
+	HidlManager *hidl_manager = HidlManager::getInstance();
+	if (!hidl_manager)
+		return;
+
+	hidl_manager->notifyHs20RxSubscriptionRemediation(
+	    wpa_s, url, osu_method);
+}
+
+void wpas_hidl_notify_hs20_rx_deauth_imminent_notice(
+    struct wpa_supplicant *wpa_s, u8 code, u16 reauth_delay, const char *url)
+{
+	if (!wpa_s || !wpa_s->global->hidl || !url)
+		return;
+
+	wpa_printf(
+	    MSG_DEBUG,
+	    "Notifying HS20 deauth imminent notice rx to hidl control: %s",
+	    url);
+
+	HidlManager *hidl_manager = HidlManager::getInstance();
+	if (!hidl_manager)
+		return;
+
+	hidl_manager->notifyHs20RxDeauthImminentNotice(
+	    wpa_s, code, reauth_delay, url);
+}
+
+void wpas_hidl_notify_disconnect_reason(struct wpa_supplicant *wpa_s)
+{
+	if (!wpa_s)
+		return;
+
+	wpa_printf(
+	    MSG_DEBUG, "Notifying disconnect reason to hidl control: %d",
+	    wpa_s->disconnect_reason);
+
+	HidlManager *hidl_manager = HidlManager::getInstance();
+	if (!hidl_manager)
+		return;
+
+	hidl_manager->notifyDisconnectReason(wpa_s);
+}
+
+void wpas_hidl_notify_assoc_reject(struct wpa_supplicant *wpa_s)
+{
+	if (!wpa_s)
+		return;
+
+	wpa_printf(
+	    MSG_DEBUG, "Notifying assoc reject to hidl control: %d",
+	    wpa_s->assoc_status_code);
+
+	HidlManager *hidl_manager = HidlManager::getInstance();
+	if (!hidl_manager)
+		return;
+
+	hidl_manager->notifyAssocReject(wpa_s);
+}
+
+void wpas_hidl_notify_auth_timeout(struct wpa_supplicant *wpa_s)
+{
+	if (!wpa_s)
+		return;
+
+	wpa_printf(MSG_DEBUG, "Notifying auth timeout to hidl control");
+
+	HidlManager *hidl_manager = HidlManager::getInstance();
+	if (!hidl_manager)
+		return;
+
+	hidl_manager->notifyAuthTimeout(wpa_s);
+}
+
+void wpas_hidl_notify_bssid_changed(struct wpa_supplicant *wpa_s)
+{
+	if (!wpa_s)
+		return;
+
+	wpa_printf(MSG_DEBUG, "Notifying bssid changed to hidl control");
+
+	HidlManager *hidl_manager = HidlManager::getInstance();
+	if (!hidl_manager)
+		return;
+
+	hidl_manager->notifyBssidChanged(wpa_s);
+}
+
+void wpas_hidl_notify_wps_event_fail(
+    struct wpa_supplicant *wpa_s, uint8_t *peer_macaddr, uint16_t config_error,
+    uint16_t error_indication)
+{
+	if (!wpa_s || !peer_macaddr)
+		return;
+
+	wpa_printf(
+	    MSG_DEBUG, "Notifying Wps event fail to hidl control: %d, %d",
+	    config_error, error_indication);
+
+	HidlManager *hidl_manager = HidlManager::getInstance();
+	if (!hidl_manager)
+		return;
+
+	hidl_manager->notifyWpsEventFail(
+	    wpa_s, peer_macaddr, config_error, error_indication);
+}
+
+void wpas_hidl_notify_wps_event_success(struct wpa_supplicant *wpa_s)
+{
+	if (!wpa_s)
+		return;
+
+	wpa_printf(MSG_DEBUG, "Notifying Wps event success to hidl control");
+
+	HidlManager *hidl_manager = HidlManager::getInstance();
+	if (!hidl_manager)
+		return;
+
+	hidl_manager->notifyWpsEventSuccess(wpa_s);
+}
+
+void wpas_hidl_notify_wps_event_pbc_overlap(struct wpa_supplicant *wpa_s)
+{
+	if (!wpa_s)
+		return;
+
+	wpa_printf(
+	    MSG_DEBUG, "Notifying Wps event PBC overlap to hidl control");
+
+	HidlManager *hidl_manager = HidlManager::getInstance();
+	if (!hidl_manager)
+		return;
+
+	hidl_manager->notifyWpsEventPbcOverlap(wpa_s);
+}
+
+void wpas_hidl_notify_p2p_device_found(
+    struct wpa_supplicant *wpa_s, const u8 *addr,
+    const struct p2p_peer_info *info, const u8 *peer_wfd_device_info,
+    u8 peer_wfd_device_info_len)
+{
+	if (!wpa_s || !addr || !info)
+		return;
+
+	wpa_printf(
+	    MSG_DEBUG, "Notifying P2P device found to hidl control " MACSTR,
+	    MAC2STR(info->p2p_device_addr));
+
+	HidlManager *hidl_manager = HidlManager::getInstance();
+	if (!hidl_manager)
+		return;
+
+	hidl_manager->notifyP2pDeviceFound(
+	    wpa_s, addr, info, peer_wfd_device_info, peer_wfd_device_info_len);
+}
+
+void wpas_hidl_notify_p2p_device_lost(
+    struct wpa_supplicant *wpa_s, const u8 *p2p_device_addr)
+{
+	if (!wpa_s || !p2p_device_addr)
+		return;
+
+	wpa_printf(
+	    MSG_DEBUG, "Notifying P2P device lost to hidl control " MACSTR,
+	    MAC2STR(p2p_device_addr));
+
+	HidlManager *hidl_manager = HidlManager::getInstance();
+	if (!hidl_manager)
+		return;
+
+	hidl_manager->notifyP2pDeviceLost(wpa_s, p2p_device_addr);
+}
+
+void wpas_hidl_notify_p2p_find_stopped(struct wpa_supplicant *wpa_s)
+{
+	if (!wpa_s)
+		return;
+
+	wpa_printf(MSG_DEBUG, "Notifying P2P find stop to hidl control");
+
+	HidlManager *hidl_manager = HidlManager::getInstance();
+	if (!hidl_manager)
+		return;
+
+	hidl_manager->notifyP2pFindStopped(wpa_s);
+}
+
+void wpas_hidl_notify_p2p_go_neg_req(
+    struct wpa_supplicant *wpa_s, const u8 *src_addr, u16 dev_passwd_id,
+    u8 go_intent)
+{
+	if (!wpa_s || !src_addr)
+		return;
+
+	wpa_printf(
+	    MSG_DEBUG,
+	    "Notifying P2P GO negotiation request to hidl control " MACSTR,
+	    MAC2STR(src_addr));
+
+	HidlManager *hidl_manager = HidlManager::getInstance();
+	if (!hidl_manager)
+		return;
+
+	hidl_manager->notifyP2pGoNegReq(
+	    wpa_s, src_addr, dev_passwd_id, go_intent);
+}
+
+void wpas_hidl_notify_p2p_go_neg_completed(
+    struct wpa_supplicant *wpa_s, const struct p2p_go_neg_results *res)
+{
+	if (!wpa_s || !res)
+		return;
+
+	wpa_printf(
+	    MSG_DEBUG,
+	    "Notifying P2P GO negotiation completed to hidl control: %d",
+	    res->status);
+
+	HidlManager *hidl_manager = HidlManager::getInstance();
+	if (!hidl_manager)
+		return;
+
+	hidl_manager->notifyP2pGoNegCompleted(wpa_s, res);
+}
+
+void wpas_hidl_notify_p2p_group_formation_failure(
+    struct wpa_supplicant *wpa_s, const char *reason)
+{
+	if (!wpa_s || !reason)
+		return;
+
+	wpa_printf(
+	    MSG_DEBUG,
+	    "Notifying P2P Group formation failure to hidl control: %s",
+	    reason);
+
+	HidlManager *hidl_manager = HidlManager::getInstance();
+	if (!hidl_manager)
+		return;
+
+	hidl_manager->notifyP2pGroupFormationFailure(wpa_s, reason);
+}
+
+void wpas_hidl_notify_p2p_group_started(
+    struct wpa_supplicant *wpa_s, const struct wpa_ssid *ssid, int persistent,
+    int client)
+{
+	if (!wpa_s || !ssid)
+		return;
+
+	wpa_printf(
+	    MSG_DEBUG, "Notifying P2P Group start to hidl control: %d",
+	    ssid->id);
+
+	HidlManager *hidl_manager = HidlManager::getInstance();
+	if (!hidl_manager)
+		return;
+
+	hidl_manager->notifyP2pGroupStarted(wpa_s, ssid, persistent, client);
+}
+
+void wpas_hidl_notify_p2p_group_removed(
+    struct wpa_supplicant *wpa_s, const struct wpa_ssid *ssid, const char *role)
+{
+	if (!wpa_s || !ssid || !role)
+		return;
+
+	wpa_printf(
+	    MSG_DEBUG, "Notifying P2P Group removed to hidl control: %d",
+	    ssid->id);
+
+	HidlManager *hidl_manager = HidlManager::getInstance();
+	if (!hidl_manager)
+		return;
+
+	hidl_manager->notifyP2pGroupRemoved(wpa_s, ssid, role);
+}
+
+void wpas_hidl_notify_p2p_invitation_received(
+    struct wpa_supplicant *wpa_s, const u8 *sa, const u8 *go_dev_addr,
+    const u8 *bssid, int id, int op_freq)
+{
+	if (!wpa_s || !sa || !go_dev_addr || !bssid)
+		return;
+
+	wpa_printf(
+	    MSG_DEBUG,
+	    "Notifying P2P invitation received to hidl control: %d " MACSTR, id,
+	    MAC2STR(bssid));
+
+	HidlManager *hidl_manager = HidlManager::getInstance();
+	if (!hidl_manager)
+		return;
+
+	hidl_manager->notifyP2pInvitationReceived(
+	    wpa_s, sa, go_dev_addr, bssid, id, op_freq);
+}
+
+void wpas_hidl_notify_p2p_invitation_result(
+    struct wpa_supplicant *wpa_s, int status, const u8 *bssid)
+{
+	if (!wpa_s)
+		return;
+	if (bssid) {
+		wpa_printf(
+			MSG_DEBUG,
+			"Notifying P2P invitation result to hidl control: " MACSTR,
+			MAC2STR(bssid));
+	} else {
+		wpa_printf(
+			MSG_DEBUG,
+			"Notifying P2P invitation result to hidl control: NULL bssid");
+	}
+
+	HidlManager *hidl_manager = HidlManager::getInstance();
+	if (!hidl_manager)
+		return;
+
+	hidl_manager->notifyP2pInvitationResult(wpa_s, status, bssid);
+}
+
+void wpas_hidl_notify_p2p_provision_discovery(
+    struct wpa_supplicant *wpa_s, const u8 *dev_addr, int request,
+    enum p2p_prov_disc_status status, u16 config_methods,
+    unsigned int generated_pin)
+{
+	if (!wpa_s || !dev_addr)
+		return;
+
+	wpa_printf(
+	    MSG_DEBUG,
+	    "Notifying P2P provision discovery to hidl control " MACSTR,
+	    MAC2STR(dev_addr));
+
+	HidlManager *hidl_manager = HidlManager::getInstance();
+	if (!hidl_manager)
+		return;
+
+	hidl_manager->notifyP2pProvisionDiscovery(
+	    wpa_s, dev_addr, request, status, config_methods, generated_pin);
+}
+
+void wpas_hidl_notify_p2p_sd_response(
+    struct wpa_supplicant *wpa_s, const u8 *sa, u16 update_indic,
+    const u8 *tlvs, size_t tlvs_len)
+{
+	if (!wpa_s || !sa || !tlvs)
+		return;
+
+	wpa_printf(
+	    MSG_DEBUG,
+	    "Notifying P2P service discovery response to hidl control " MACSTR,
+	    MAC2STR(sa));
+
+	HidlManager *hidl_manager = HidlManager::getInstance();
+	if (!hidl_manager)
+		return;
+
+	hidl_manager->notifyP2pSdResponse(
+	    wpa_s, sa, update_indic, tlvs, tlvs_len);
+}
+
+void wpas_hidl_notify_ap_sta_authorized(
+    struct wpa_supplicant *wpa_s, const u8 *sta, const u8 *p2p_dev_addr)
+{
+	if (!wpa_s || !sta)
+		return;
+
+	wpa_printf(
+	    MSG_DEBUG,
+	    "Notifying P2P AP STA authorized to hidl control " MACSTR,
+	    MAC2STR(sta));
+
+	HidlManager *hidl_manager = HidlManager::getInstance();
+	if (!hidl_manager)
+		return;
+
+	hidl_manager->notifyApStaAuthorized(wpa_s, sta, p2p_dev_addr);
+}
+
+void wpas_hidl_notify_ap_sta_deauthorized(
+    struct wpa_supplicant *wpa_s, const u8 *sta, const u8 *p2p_dev_addr)
+{
+	if (!wpa_s || !sta)
+		return;
+
+	wpa_printf(
+	    MSG_DEBUG,
+	    "Notifying P2P AP STA deauthorized to hidl control " MACSTR,
+	    MAC2STR(sta));
+
+	HidlManager *hidl_manager = HidlManager::getInstance();
+	if (!hidl_manager)
+		return;
+
+	hidl_manager->notifyApStaDeauthorized(wpa_s, sta, p2p_dev_addr);
+}
+
+void wpas_hidl_notify_eap_error(
+    struct wpa_supplicant *wpa_s, int error_code)
+{
+	if (!wpa_s)
+		return;
+
+	wpa_printf(
+	    MSG_DEBUG,
+            "Notifying EAP Error: %d ", error_code);
+
+	HidlManager *hidl_manager = HidlManager::getInstance();
+	if (!hidl_manager)
+		return;
+
+	hidl_manager->notifyEapError(wpa_s, error_code);
+}
+
diff --git a/wpa_supplicant/hidl/1.1/hidl.h b/wpa_supplicant/hidl/1.1/hidl.h
new file mode 100644
index 0000000..1dfadc6
--- /dev/null
+++ b/wpa_supplicant/hidl/1.1/hidl.h
@@ -0,0 +1,226 @@
+/*
+ * 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);
+void wpas_hidl_notify_anqp_query_done(
+    struct wpa_supplicant *wpa_s, const u8 *bssid, const char *result,
+    const struct wpa_bss_anqp *anqp);
+void wpas_hidl_notify_hs20_icon_query_done(
+    struct wpa_supplicant *wpa_s, const u8 *bssid, const char *file_name,
+    const u8 *image, u32 image_length);
+void wpas_hidl_notify_hs20_rx_subscription_remediation(
+    struct wpa_supplicant *wpa_s, const char *url, u8 osu_method);
+void wpas_hidl_notify_hs20_rx_deauth_imminent_notice(
+    struct wpa_supplicant *wpa_s, u8 code, u16 reauth_delay, const char *url);
+void wpas_hidl_notify_disconnect_reason(struct wpa_supplicant *wpa_s);
+void wpas_hidl_notify_assoc_reject(struct wpa_supplicant *wpa_s);
+void wpas_hidl_notify_auth_timeout(struct wpa_supplicant *wpa_s);
+void wpas_hidl_notify_bssid_changed(struct wpa_supplicant *wpa_s);
+void wpas_hidl_notify_wps_event_fail(
+    struct wpa_supplicant *wpa_s, uint8_t *peer_macaddr, uint16_t config_error,
+    uint16_t error_indication);
+void wpas_hidl_notify_wps_event_success(struct wpa_supplicant *wpa_s);
+void wpas_hidl_notify_wps_event_pbc_overlap(struct wpa_supplicant *wpa_s);
+void wpas_hidl_notify_p2p_device_found(
+    struct wpa_supplicant *wpa_s, const u8 *addr,
+    const struct p2p_peer_info *info, const u8 *peer_wfd_device_info,
+    u8 peer_wfd_device_info_len);
+void wpas_hidl_notify_p2p_device_lost(
+    struct wpa_supplicant *wpa_s, const u8 *p2p_device_addr);
+void wpas_hidl_notify_p2p_find_stopped(struct wpa_supplicant *wpa_s);
+void wpas_hidl_notify_p2p_go_neg_req(
+    struct wpa_supplicant *wpa_s, const u8 *src_addr, u16 dev_passwd_id,
+    u8 go_intent);
+void wpas_hidl_notify_p2p_go_neg_completed(
+    struct wpa_supplicant *wpa_s, const struct p2p_go_neg_results *res);
+void wpas_hidl_notify_p2p_group_formation_failure(
+    struct wpa_supplicant *wpa_s, const char *reason);
+void wpas_hidl_notify_p2p_group_started(
+    struct wpa_supplicant *wpa_s, const struct wpa_ssid *ssid, int persistent,
+    int client);
+void wpas_hidl_notify_p2p_group_removed(
+    struct wpa_supplicant *wpa_s, const struct wpa_ssid *ssid,
+    const char *role);
+void wpas_hidl_notify_p2p_invitation_received(
+    struct wpa_supplicant *wpa_s, const u8 *sa, const u8 *go_dev_addr,
+    const u8 *bssid, int id, int op_freq);
+void wpas_hidl_notify_p2p_invitation_result(
+    struct wpa_supplicant *wpa_s, int status, const u8 *bssid);
+void wpas_hidl_notify_p2p_provision_discovery(
+    struct wpa_supplicant *wpa_s, const u8 *dev_addr, int request,
+    enum p2p_prov_disc_status status, u16 config_methods,
+    unsigned int generated_pin);
+void wpas_hidl_notify_p2p_sd_response(
+    struct wpa_supplicant *wpa_s, const u8 *sa, u16 update_indic,
+    const u8 *tlvs, size_t tlvs_len);
+void wpas_hidl_notify_ap_sta_authorized(
+    struct wpa_supplicant *wpa_s, const u8 *sta, const u8 *p2p_dev_addr);
+void wpas_hidl_notify_ap_sta_deauthorized(
+    struct wpa_supplicant *wpa_s, const u8 *sta, const u8 *p2p_dev_addr);
+void wpas_hidl_notify_eap_error(struct wpa_supplicant *wpa_s, int error_code);
+#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;
+}
+static void wpas_hidl_notify_anqp_query_done(
+    struct wpa_supplicant *wpa_s, const u8 *bssid, const char *result,
+    const struct wpa_bss_anqp *anqp)
+{
+}
+static void wpas_hidl_notify_hs20_icon_query_done(
+    struct wpa_supplicant *wpa_s, const u8 *bssid, const char *file_name,
+    const u8 *image, u32 image_length)
+{
+}
+static void wpas_hidl_notify_hs20_rx_subscription_remediation(
+    struct wpa_supplicant *wpa_s, const char *url, u8 osu_method)
+{
+}
+static void wpas_hidl_notify_hs20_rx_deauth_imminent_notice(
+    struct wpa_supplicant *wpa_s, u8 code, u16 reauth_delay, const char *url)
+{
+}
+static void wpas_hidl_notify_disconnect_reason(struct wpa_supplicant *wpa_s) {}
+static void wpas_hidl_notify_assoc_reject(struct wpa_supplicant *wpa_s) {}
+static void wpas_hidl_notify_auth_timeout(struct wpa_supplicant *wpa_s) {}
+static void wpas_hidl_notify_wps_event_fail(
+    struct wpa_supplicant *wpa_s, uint8_t *peer_macaddr, uint16_t config_error,
+    uint16_t error_indication)
+{
+}
+static void wpas_hidl_notify_bssid_changed(struct wpa_supplicant *wpa_s) {}
+static void wpas_hidl_notify_wps_event_success(struct wpa_supplicant *wpa_s) {}
+static void wpas_hidl_notify_wps_event_pbc_overlap(struct wpa_supplicant *wpa_s)
+{
+}
+static void wpas_hidl_notify_p2p_device_found(
+    struct wpa_supplicant *wpa_s, const u8 *addr,
+    const struct p2p_peer_info *info, const u8 *peer_wfd_device_info,
+    u8 peer_wfd_device_info_len);
+{
+}
+static void wpas_hidl_notify_p2p_device_lost(
+    struct wpa_supplicant *wpa_s, const u8 *p2p_device_addr)
+{
+}
+static void wpas_hidl_notify_p2p_find_stopped(struct wpa_supplicant *wpa_s) {}
+static void wpas_hidl_notify_p2p_go_neg_req(
+    struct wpa_supplicant *wpa_s, const u8 *src_addr, u16 dev_passwd_id,
+    u8 go_intent)
+{
+}
+static void wpas_hidl_notify_p2p_go_neg_completed(
+    struct wpa_supplicant *wpa_s, const struct p2p_go_neg_results *res)
+{
+}
+static void wpas_hidl_notify_p2p_group_formation_failure(
+    struct wpa_supplicant *wpa_s, const char *reason)
+{
+}
+static void wpas_hidl_notify_p2p_group_started(
+    struct wpa_supplicant *wpa_s, const struct wpa_ssid *ssid, int persistent,
+    int client)
+{
+}
+static void wpas_hidl_notify_p2p_group_removed(
+    struct wpa_supplicant *wpa_s, const struct wpa_ssid *ssid, const char *role)
+{
+}
+static void wpas_hidl_notify_p2p_invitation_received(
+    struct wpa_supplicant *wpa_s, const u8 *sa, const u8 *go_dev_addr,
+    const u8 *bssid, int id, int op_freq)
+{
+}
+static void wpas_hidl_notify_p2p_invitation_result(
+    struct wpa_supplicant *wpa_s, int status, const u8 *bssid)
+{
+}
+static void wpas_hidl_notify_p2p_provision_discovery(
+    struct wpa_supplicant *wpa_s, const u8 *dev_addr, int request,
+    enum p2p_prov_disc_status status, u16 config_methods,
+    unsigned int generated_pin)
+{
+}
+static void wpas_hidl_notify_p2p_sd_response(
+    struct wpa_supplicant *wpa_s, const u8 *sa, u16 update_indic,
+    const u8 *tlvs, size_t tlvs_len)
+{
+}
+static void wpas_hidl_notify_ap_sta_authorized(
+    struct wpa_supplicant *wpa_s, const u8 *sta, const u8 *p2p_dev_addr)
+{
+}
+static void wpas_hidl_notify_ap_sta_deauthorized(
+    struct wpa_supplicant *wpa_s, const u8 *sta, const u8 *p2p_dev_addr)
+{
+}
+static void wpas_hidl_notify_eap_error(
+    struct wpa_supplicant *wpa_s, int error_code)
+{
+}
+#endif  // CONFIG_CTRL_IFACE_HIDL
+
+#ifdef _cplusplus
+}
+#endif  // _cplusplus
+
+#endif  // WPA_SUPPLICANT_HIDL_HIDL_H
diff --git a/wpa_supplicant/hidl/1.1/hidl_constants.h b/wpa_supplicant/hidl/1.1/hidl_constants.h
new file mode 100644
index 0000000..988a590
--- /dev/null
+++ b/wpa_supplicant/hidl/1.1/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/1.1/hidl_i.h b/wpa_supplicant/hidl/1.1/hidl_i.h
new file mode 100644
index 0000000..c7a0142
--- /dev/null
+++ b/wpa_supplicant/hidl/1.1/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/1.1/hidl_manager.cpp b/wpa_supplicant/hidl/1.1/hidl_manager.cpp
new file mode 100644
index 0000000..ca614d2
--- /dev/null
+++ b/wpa_supplicant/hidl/1.1/hidl_manager.cpp
@@ -0,0 +1,1845 @@
+/*
+ * 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 <regex>
+
+#include "hidl_manager.h"
+#include "misc_utils.h"
+
+extern "C" {
+#include "src/eap_common/eap_sim_common.h"
+}
+
+namespace {
+using android::hardware::hidl_array;
+
+constexpr uint8_t kWfdDeviceInfoLen = 6;
+// GSM-AUTH:<RAND1>:<RAND2>[:<RAND3>]
+constexpr char kGsmAuthRegex2[] = "GSM-AUTH:([0-9a-f]+):([0-9a-f]+)";
+constexpr char kGsmAuthRegex3[] =
+    "GSM-AUTH:([0-9a-f]+):([0-9a-f]+):([0-9a-f]+)";
+// UMTS-AUTH:<RAND>:<AUTN>
+constexpr char kUmtsAuthRegex[] = "UMTS-AUTH:([0-9a-f]+):([0-9a-f]+)";
+constexpr size_t kGsmRandLenBytes = GSM_RAND_LEN;
+constexpr size_t kUmtsRandLenBytes = EAP_AKA_RAND_LEN;
+constexpr size_t kUmtsAutnLenBytes = EAP_AKA_AUTN_LEN;
+constexpr u8 kZeroBssid[6] = {0, 0, 0, 0, 0, 0};
+/**
+ * Check if the provided |wpa_supplicant| structure represents a P2P iface or
+ * not.
+ */
+constexpr bool isP2pIface(const struct wpa_supplicant *wpa_s)
+{
+	return (wpa_s->global->p2p_init_wpa_s == wpa_s);
+}
+
+/**
+ * Creates a unique key for the network using the provided |ifname| and
+ * |network_id| to be used in the internal map of |ISupplicantNetwork| 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 getNetworkObjectMapKey(
+    const std::string &ifname, int network_id)
+{
+	return ifname + "_" + std::to_string(network_id);
+}
+
+/**
+ * Add callback to the corresponding list after linking to death on the
+ * corresponding hidl object reference.
+ */
+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)
+{
+#if 0   // TODO(b/31632518): HIDL object death notifications.
+	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!
+	if (android::hardware::IInterface::asBinder(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;
+	}
+#endif  // TODO(b/31632518): HIDL object death notifications.
+	callback_list.push_back(callback);
+	return 0;
+}
+
+template <class ObjectType>
+int addHidlObjectToMap(
+    const std::string &key, const android::sp<ObjectType> object,
+    std::map<const std::string, android::sp<ObjectType>> &object_map)
+{
+	// Return failure if we already have an object for that |key|.
+	if (object_map.find(key) != object_map.end())
+		return 1;
+	object_map[key] = object;
+	if (!object_map[key].get())
+		return 1;
+	return 0;
+}
+
+template <class ObjectType>
+int removeHidlObjectFromMap(
+    const std::string &key,
+    std::map<const std::string, android::sp<ObjectType>> &object_map)
+{
+	// Return failure if we dont have an object for that |key|.
+	const auto &object_iter = object_map.find(key);
+	if (object_iter == object_map.end())
+		return 1;
+	object_iter->second->invalidate();
+	object_map.erase(object_iter);
+	return 0;
+}
+
+template <class CallbackType>
+int addIfaceCallbackHidlObjectToMap(
+    const std::string &ifname, const android::sp<CallbackType> &callback,
+    const std::function<void(const android::sp<CallbackType> &)>
+	&on_hidl_died_fctor,
+    std::map<const std::string, std::vector<android::sp<CallbackType>>>
+	&callbacks_map)
+{
+	if (ifname.empty())
+		return 1;
+
+	auto iface_callback_map_iter = callbacks_map.find(ifname);
+	if (iface_callback_map_iter == 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.
+	return registerForDeathAndAddCallbackHidlObjectToList<CallbackType>(
+	    callback, on_hidl_died_fctor, iface_callback_list);
+}
+
+template <class CallbackType>
+int addNetworkCallbackHidlObjectToMap(
+    const std::string &ifname, int network_id,
+    const android::sp<CallbackType> &callback,
+    const std::function<void(const android::sp<CallbackType> &)>
+	&on_hidl_died_fctor,
+    std::map<const std::string, std::vector<android::sp<CallbackType>>>
+	&callbacks_map)
+{
+	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 = callbacks_map.find(network_key);
+	if (network_callback_map_iter == 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.
+	return registerForDeathAndAddCallbackHidlObjectToList<CallbackType>(
+	    callback, on_hidl_died_fctor, network_callback_list);
+}
+
+template <class CallbackType>
+int removeAllIfaceCallbackHidlObjectsFromMap(
+    const std::string &ifname,
+    std::map<const std::string, std::vector<android::sp<CallbackType>>>
+	&callbacks_map)
+{
+	auto iface_callback_map_iter = callbacks_map.find(ifname);
+	if (iface_callback_map_iter == callbacks_map.end())
+		return 1;
+#if 0   // TODO(b/31632518): HIDL object death notifications.
+	const auto &iface_callback_list = iface_callback_map_iter->second;
+	for (const auto &callback : iface_callback_list) {
+		if (android::hardware::IInterface::asBinder(callback)
+			->unlinkToDeath(nullptr, callback.get()) !=
+		    android::OK) {
+			wpa_printf(
+			    MSG_ERROR,
+			    "Error deregistering for death notification for "
+			    "iface callback object");
+		}
+	}
+#endif  // TODO(b/31632518): HIDL object death notifications.
+	callbacks_map.erase(iface_callback_map_iter);
+	return 0;
+}
+
+template <class CallbackType>
+int removeAllNetworkCallbackHidlObjectsFromMap(
+    const std::string &network_key,
+    std::map<const std::string, std::vector<android::sp<CallbackType>>>
+	&callbacks_map)
+{
+	auto network_callback_map_iter = callbacks_map.find(network_key);
+	if (network_callback_map_iter == callbacks_map.end())
+		return 1;
+#if 0   // TODO(b/31632518): HIDL object death notifications.
+	const auto &network_callback_list = network_callback_map_iter->second;
+	for (const auto &callback : network_callback_list) {
+		if (android::hardware::IInterface::asBinder(callback)
+			->unlinkToDeath(nullptr, callback.get()) !=
+		    android::OK) {
+			wpa_printf(
+			    MSG_ERROR,
+			    "Error deregistering for death "
+			    "notification for "
+			    "network callback object");
+		}
+	}
+#endif  // TODO(b/31632518): HIDL object death notifications.
+	callbacks_map.erase(network_callback_map_iter);
+	return 0;
+}
+
+template <class CallbackType>
+void removeIfaceCallbackHidlObjectFromMap(
+    const std::string &ifname, const android::sp<CallbackType> &callback,
+    std::map<const std::string, std::vector<android::sp<CallbackType>>>
+	&callbacks_map)
+{
+	if (ifname.empty())
+		return;
+
+	auto iface_callback_map_iter = callbacks_map.find(ifname);
+	if (iface_callback_map_iter == 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());
+}
+
+template <class CallbackType>
+void removeNetworkCallbackHidlObjectFromMap(
+    const std::string &ifname, int network_id,
+    const android::sp<CallbackType> &callback,
+    std::map<const std::string, std::vector<android::sp<CallbackType>>>
+	&callbacks_map)
+{
+	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 = callbacks_map.find(network_key);
+	if (network_callback_map_iter == 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());
+}
+
+template <class CallbackType>
+void callWithEachIfaceCallback(
+    const std::string &ifname,
+    const std::function<
+	android::hardware::Return<void>(android::sp<CallbackType>)> &method,
+    const std::map<const std::string, std::vector<android::sp<CallbackType>>>
+	&callbacks_map)
+{
+	if (ifname.empty())
+		return;
+
+	auto iface_callback_map_iter = callbacks_map.find(ifname);
+	if (iface_callback_map_iter == callbacks_map.end())
+		return;
+	const auto &iface_callback_list = iface_callback_map_iter->second;
+	for (const auto &callback : iface_callback_list) {
+		if (!method(callback).isOk()) {
+			wpa_printf(
+			    MSG_ERROR, "Failed to invoke HIDL iface callback");
+		}
+	}
+}
+
+template <class CallbackTypeV1_0, class CallbackTypeV1_1>
+void callWithEachIfaceCallback_1_1(
+    const std::string &ifname,
+    const std::function<
+	android::hardware::Return<void>(android::sp<CallbackTypeV1_1>)> &method,
+    const std::map<const std::string, std::vector<android::sp<CallbackTypeV1_0>>>
+	&callbacks_map)
+{
+	if (ifname.empty())
+		return;
+
+	auto iface_callback_map_iter = callbacks_map.find(ifname);
+	if (iface_callback_map_iter == callbacks_map.end())
+		return;
+	const auto &iface_callback_list = iface_callback_map_iter->second;
+	for (const auto &callback : iface_callback_list) {
+		android::sp<CallbackTypeV1_1> callback_1_1 =
+		    CallbackTypeV1_1::castFrom(callback);
+		if (callback_1_1 == nullptr)
+			continue;
+
+		if (!method(callback_1_1).isOk()) {
+			wpa_printf(
+			    MSG_ERROR, "Failed to invoke HIDL iface callback");
+		}
+	}
+}
+
+template <class CallbackType>
+void callWithEachNetworkCallback(
+    const std::string &ifname, int network_id,
+    const std::function<
+	android::hardware::Return<void>(android::sp<CallbackType>)> &method,
+    const std::map<const std::string, std::vector<android::sp<CallbackType>>>
+	&callbacks_map)
+{
+	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 = callbacks_map.find(network_key);
+	if (network_callback_map_iter == callbacks_map.end())
+		return;
+	const auto &network_callback_list = network_callback_map_iter->second;
+	for (const auto &callback : network_callback_list) {
+		if (!method(callback).isOk()) {
+			wpa_printf(
+			    MSG_ERROR,
+			    "Failed to invoke HIDL network callback");
+		}
+	}
+}
+
+int parseGsmAuthNetworkRequest(
+    const std::string &params_str,
+    std::vector<hidl_array<uint8_t, kGsmRandLenBytes>> *out_rands)
+{
+	std::smatch matches;
+	std::regex params_gsm_regex2(kGsmAuthRegex2);
+	std::regex params_gsm_regex3(kGsmAuthRegex3);
+	if (!std::regex_match(params_str, matches, params_gsm_regex3) &&
+	    !std::regex_match(params_str, matches, params_gsm_regex2)) {
+		return 1;
+	}
+	for (uint32_t i = 1; i < matches.size(); i++) {
+		hidl_array<uint8_t, kGsmRandLenBytes> rand;
+		const auto &match = matches[i];
+		WPA_ASSERT(match.size() >= 2 * rand.size());
+		if (hexstr2bin(match.str().c_str(), rand.data(), rand.size())) {
+			wpa_printf(
+			    MSG_ERROR, "Failed to parse GSM auth params");
+			return 1;
+		}
+		out_rands->push_back(rand);
+	}
+	return 0;
+}
+
+int parseUmtsAuthNetworkRequest(
+    const std::string &params_str,
+    hidl_array<uint8_t, kUmtsRandLenBytes> *out_rand,
+    hidl_array<uint8_t, kUmtsAutnLenBytes> *out_autn)
+{
+	std::smatch matches;
+	std::regex params_umts_regex(kUmtsAuthRegex);
+	if (!std::regex_match(params_str, matches, params_umts_regex)) {
+		return 1;
+	}
+	WPA_ASSERT(matches[1].size() >= 2 * out_rand->size());
+	if (hexstr2bin(
+		matches[1].str().c_str(), out_rand->data(), out_rand->size())) {
+		wpa_printf(MSG_ERROR, "Failed to parse UMTS auth params");
+		return 1;
+	}
+	WPA_ASSERT(matches[2].size() >= 2 * out_autn->size());
+	if (hexstr2bin(
+		matches[2].str().c_str(), out_autn->data(), out_autn->size())) {
+		wpa_printf(MSG_ERROR, "Failed to parse UMTS auth params");
+		return 1;
+	}
+	return 0;
+}
+}  // namespace
+
+namespace android {
+namespace hardware {
+namespace wifi {
+namespace supplicant {
+namespace V1_1 {
+namespace implementation {
+
+using namespace android::hardware::wifi::supplicant::V1_0;
+using namespace android::hardware::wifi::supplicant::V1_1;
+using V1_0::ISupplicantStaIfaceCallback;
+
+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 it.
+	supplicant_object_ = new Supplicant(global);
+	if (supplicant_object_->registerAsService() != android::NO_ERROR) {
+		return 1;
+	}
+	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;
+
+	if (isP2pIface(wpa_s)) {
+		if (addHidlObjectToMap<P2pIface>(
+			wpa_s->ifname,
+			new P2pIface(wpa_s->global, wpa_s->ifname),
+			p2p_iface_object_map_)) {
+			wpa_printf(
+			    MSG_ERROR,
+			    "Failed to register P2P interface with HIDL "
+			    "control: %s",
+			    wpa_s->ifname);
+			return 1;
+		}
+		p2p_iface_callbacks_map_[wpa_s->ifname] =
+		    std::vector<android::sp<ISupplicantP2pIfaceCallback>>();
+	} else {
+		if (addHidlObjectToMap<StaIface>(
+			wpa_s->ifname,
+			new StaIface(wpa_s->global, wpa_s->ifname),
+			sta_iface_object_map_)) {
+			wpa_printf(
+			    MSG_ERROR,
+			    "Failed to register STA interface with HIDL "
+			    "control: %s",
+			    wpa_s->ifname);
+			return 1;
+		}
+		sta_iface_callbacks_map_[wpa_s->ifname] =
+		    std::vector<android::sp<ISupplicantStaIfaceCallback>>();
+	}
+
+	// Invoke the |onInterfaceCreated| method on all registered callbacks.
+	callWithEachSupplicantCallback(std::bind(
+	    &ISupplicantCallback::onInterfaceCreated, std::placeholders::_1,
+	    wpa_s->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;
+
+	// Check if this interface is present in P2P map first, else check in
+	// STA map.
+	// Note: We can't use isP2pIface() here because interface
+	// pointers (wpa_s->global->p2p_init_wpa_s == wpa_s) used by the helper
+	// function is cleared by the core before notifying the HIDL interface.
+	bool success =
+	    !removeHidlObjectFromMap(wpa_s->ifname, p2p_iface_object_map_);
+	if (success) {  // assumed to be P2P
+		success = !removeAllIfaceCallbackHidlObjectsFromMap(
+		    wpa_s->ifname, p2p_iface_callbacks_map_);
+	} else {  // assumed to be STA
+		success = !removeHidlObjectFromMap(
+		    wpa_s->ifname, sta_iface_object_map_);
+		if (success) {
+			success = !removeAllIfaceCallbackHidlObjectsFromMap(
+			    wpa_s->ifname, sta_iface_callbacks_map_);
+		}
+	}
+	if (!success) {
+		wpa_printf(
+		    MSG_ERROR,
+		    "Failed to unregister interface with HIDL "
+		    "control: %s",
+		    wpa_s->ifname);
+		return 1;
+	}
+
+	// Invoke the |onInterfaceRemoved| method on all registered callbacks.
+	callWithEachSupplicantCallback(std::bind(
+	    &ISupplicantCallback::onInterfaceRemoved, std::placeholders::_1,
+	    wpa_s->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 (isP2pIface(wpa_s)) {
+		if (addHidlObjectToMap<P2pNetwork>(
+			network_key,
+			new P2pNetwork(wpa_s->global, wpa_s->ifname, ssid->id),
+			p2p_network_object_map_)) {
+			wpa_printf(
+			    MSG_ERROR,
+			    "Failed to register P2P network with HIDL "
+			    "control: %d",
+			    ssid->id);
+			return 1;
+		}
+		p2p_network_callbacks_map_[network_key] =
+		    std::vector<android::sp<ISupplicantP2pNetworkCallback>>();
+		// Invoke the |onNetworkAdded| method on all registered
+		// callbacks.
+		callWithEachP2pIfaceCallback(
+		    wpa_s->ifname,
+		    std::bind(
+			&ISupplicantP2pIfaceCallback::onNetworkAdded,
+			std::placeholders::_1, ssid->id));
+	} else {
+		if (addHidlObjectToMap<StaNetwork>(
+			network_key,
+			new StaNetwork(wpa_s->global, wpa_s->ifname, ssid->id),
+			sta_network_object_map_)) {
+			wpa_printf(
+			    MSG_ERROR,
+			    "Failed to register STA network with HIDL "
+			    "control: %d",
+			    ssid->id);
+			return 1;
+		}
+		sta_network_callbacks_map_[network_key] =
+		    std::vector<android::sp<ISupplicantStaNetworkCallback>>();
+		// Invoke the |onNetworkAdded| method on all registered
+		// callbacks.
+		callWithEachStaIfaceCallback(
+		    wpa_s->ifname,
+		    std::bind(
+			&ISupplicantStaIfaceCallback::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 (isP2pIface(wpa_s)) {
+		if (removeHidlObjectFromMap(
+			network_key, p2p_network_object_map_)) {
+			wpa_printf(
+			    MSG_ERROR,
+			    "Failed to unregister P2P network with HIDL "
+			    "control: %d",
+			    ssid->id);
+			return 1;
+		}
+		if (removeAllNetworkCallbackHidlObjectsFromMap(
+			network_key, p2p_network_callbacks_map_))
+			return 1;
+
+		// Invoke the |onNetworkRemoved| method on all registered
+		// callbacks.
+		callWithEachP2pIfaceCallback(
+		    wpa_s->ifname,
+		    std::bind(
+			&ISupplicantP2pIfaceCallback::onNetworkRemoved,
+			std::placeholders::_1, ssid->id));
+	} else {
+		if (removeHidlObjectFromMap(
+			network_key, sta_network_object_map_)) {
+			wpa_printf(
+			    MSG_ERROR,
+			    "Failed to unregister STA network with HIDL "
+			    "control: %d",
+			    ssid->id);
+			return 1;
+		}
+		if (removeAllNetworkCallbackHidlObjectsFromMap(
+			network_key, sta_network_callbacks_map_))
+			return 1;
+
+		// Invoke the |onNetworkRemoved| method on all registered
+		// callbacks.
+		callWithEachStaIfaceCallback(
+		    wpa_s->ifname,
+		    std::bind(
+			&ISupplicantStaIfaceCallback::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;
+
+	if (sta_iface_object_map_.find(wpa_s->ifname) ==
+	    sta_iface_object_map_.end())
+		return 1;
+
+	// Invoke the |onStateChanged| method on all registered callbacks.
+	uint32_t hidl_network_id = UINT32_MAX;
+	std::vector<uint8_t> hidl_ssid;
+	if (wpa_s->current_ssid) {
+		hidl_network_id = wpa_s->current_ssid->id;
+		hidl_ssid.assign(
+		    wpa_s->current_ssid->ssid,
+		    wpa_s->current_ssid->ssid + wpa_s->current_ssid->ssid_len);
+	}
+	uint8_t *bssid;
+	// wpa_supplicant sets the |pending_bssid| field when it starts a
+	// connection. Only after association state does it update the |bssid|
+	// field. So, in the HIDL callback send the appropriate bssid.
+	if (wpa_s->wpa_state <= WPA_ASSOCIATED) {
+		bssid = wpa_s->pending_bssid;
+	} else {
+		bssid = wpa_s->bssid;
+	}
+	callWithEachStaIfaceCallback(
+	    wpa_s->ifname, std::bind(
+			       &ISupplicantStaIfaceCallback::onStateChanged,
+			       std::placeholders::_1,
+			       static_cast<ISupplicantStaIfaceCallback::State>(
+				   wpa_s->wpa_state),
+			       bssid, hidl_network_id, hidl_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 (sta_network_object_map_.find(network_key) ==
+	    sta_network_object_map_.end())
+		return 1;
+
+	if (type == WPA_CTRL_REQ_EAP_IDENTITY) {
+		callWithEachStaNetworkCallback(
+		    wpa_s->ifname, ssid->id,
+		    std::bind(
+			&ISupplicantStaNetworkCallback::
+			    onNetworkEapIdentityRequest,
+			std::placeholders::_1));
+		return 0;
+	}
+	if (type == WPA_CTRL_REQ_SIM) {
+		std::vector<hidl_array<uint8_t, 16>> gsm_rands;
+		hidl_array<uint8_t, 16> umts_rand;
+		hidl_array<uint8_t, 16> umts_autn;
+		if (!parseGsmAuthNetworkRequest(param, &gsm_rands)) {
+			ISupplicantStaNetworkCallback::
+			    NetworkRequestEapSimGsmAuthParams hidl_params;
+			hidl_params.rands = gsm_rands;
+			callWithEachStaNetworkCallback(
+			    wpa_s->ifname, ssid->id,
+			    std::bind(
+				&ISupplicantStaNetworkCallback::
+				    onNetworkEapSimGsmAuthRequest,
+				std::placeholders::_1, hidl_params));
+			return 0;
+		}
+		if (!parseUmtsAuthNetworkRequest(
+			param, &umts_rand, &umts_autn)) {
+			ISupplicantStaNetworkCallback::
+			    NetworkRequestEapSimUmtsAuthParams hidl_params;
+			hidl_params.rand = umts_rand;
+			hidl_params.autn = umts_autn;
+			callWithEachStaNetworkCallback(
+			    wpa_s->ifname, ssid->id,
+			    std::bind(
+				&ISupplicantStaNetworkCallback::
+				    onNetworkEapSimUmtsAuthRequest,
+				std::placeholders::_1, hidl_params));
+			return 0;
+		}
+	}
+	return 1;
+}
+
+/**
+ * Notify all listeners about the end of an ANQP query.
+ *
+ * @param wpa_s |wpa_supplicant| struct corresponding to the interface.
+ * @param bssid BSSID of the access point.
+ * @param result Result of the operation ("SUCCESS" or "FAILURE").
+ * @param anqp |wpa_bss_anqp| ANQP data fetched.
+ */
+void HidlManager::notifyAnqpQueryDone(
+    struct wpa_supplicant *wpa_s, const u8 *bssid, const char *result,
+    const struct wpa_bss_anqp *anqp)
+{
+	if (!wpa_s || !bssid || !result || !anqp)
+		return;
+
+	if (sta_iface_object_map_.find(wpa_s->ifname) ==
+	    sta_iface_object_map_.end())
+		return;
+
+	ISupplicantStaIfaceCallback::AnqpData hidl_anqp_data;
+	ISupplicantStaIfaceCallback::Hs20AnqpData hidl_hs20_anqp_data;
+	if (std::string(result) == "SUCCESS") {
+		hidl_anqp_data.venueName =
+		    misc_utils::convertWpaBufToVector(anqp->venue_name);
+		hidl_anqp_data.roamingConsortium =
+		    misc_utils::convertWpaBufToVector(anqp->roaming_consortium);
+		hidl_anqp_data.ipAddrTypeAvailability =
+		    misc_utils::convertWpaBufToVector(
+			anqp->ip_addr_type_availability);
+		hidl_anqp_data.naiRealm =
+		    misc_utils::convertWpaBufToVector(anqp->nai_realm);
+		hidl_anqp_data.anqp3gppCellularNetwork =
+		    misc_utils::convertWpaBufToVector(anqp->anqp_3gpp);
+		hidl_anqp_data.domainName =
+		    misc_utils::convertWpaBufToVector(anqp->domain_name);
+
+		hidl_hs20_anqp_data.operatorFriendlyName =
+		    misc_utils::convertWpaBufToVector(
+			anqp->hs20_operator_friendly_name);
+		hidl_hs20_anqp_data.wanMetrics =
+		    misc_utils::convertWpaBufToVector(anqp->hs20_wan_metrics);
+		hidl_hs20_anqp_data.connectionCapability =
+		    misc_utils::convertWpaBufToVector(
+			anqp->hs20_connection_capability);
+		hidl_hs20_anqp_data.osuProvidersList =
+		    misc_utils::convertWpaBufToVector(
+			anqp->hs20_osu_providers_list);
+	}
+
+	callWithEachStaIfaceCallback(
+	    wpa_s->ifname, std::bind(
+			       &ISupplicantStaIfaceCallback::onAnqpQueryDone,
+			       std::placeholders::_1, bssid, hidl_anqp_data,
+			       hidl_hs20_anqp_data));
+}
+
+/**
+ * Notify all listeners about the end of an HS20 icon query.
+ *
+ * @param wpa_s |wpa_supplicant| struct corresponding to the interface.
+ * @param bssid BSSID of the access point.
+ * @param file_name Name of the icon file.
+ * @param image Raw bytes of the icon file.
+ * @param image_length Size of the the icon file.
+ */
+void HidlManager::notifyHs20IconQueryDone(
+    struct wpa_supplicant *wpa_s, const u8 *bssid, const char *file_name,
+    const u8 *image, u32 image_length)
+{
+	if (!wpa_s || !bssid || !file_name || !image)
+		return;
+
+	if (sta_iface_object_map_.find(wpa_s->ifname) ==
+	    sta_iface_object_map_.end())
+		return;
+
+	callWithEachStaIfaceCallback(
+	    wpa_s->ifname,
+	    std::bind(
+		&ISupplicantStaIfaceCallback::onHs20IconQueryDone,
+		std::placeholders::_1, bssid, file_name,
+		std::vector<uint8_t>(image, image + image_length)));
+}
+
+/**
+ * Notify all listeners about the reception of HS20 subscription
+ * remediation notification from the server.
+ *
+ * @param wpa_s |wpa_supplicant| struct corresponding to the interface.
+ * @param url URL of the server.
+ * @param osu_method OSU method (OMA_DM or SOAP_XML_SPP).
+ */
+void HidlManager::notifyHs20RxSubscriptionRemediation(
+    struct wpa_supplicant *wpa_s, const char *url, u8 osu_method)
+{
+	if (!wpa_s || !url)
+		return;
+
+	if (sta_iface_object_map_.find(wpa_s->ifname) ==
+	    sta_iface_object_map_.end())
+		return;
+
+	ISupplicantStaIfaceCallback::OsuMethod hidl_osu_method = {};
+	if (osu_method & 0x1) {
+		hidl_osu_method =
+		    ISupplicantStaIfaceCallback::OsuMethod::OMA_DM;
+	} else if (osu_method & 0x2) {
+		hidl_osu_method =
+		    ISupplicantStaIfaceCallback::OsuMethod::SOAP_XML_SPP;
+	}
+	callWithEachStaIfaceCallback(
+	    wpa_s->ifname,
+	    std::bind(
+		&ISupplicantStaIfaceCallback::onHs20SubscriptionRemediation,
+		std::placeholders::_1, wpa_s->bssid, hidl_osu_method, url));
+}
+
+/**
+ * Notify all listeners about the reception of HS20 immient deauth
+ * notification from the server.
+ *
+ * @param wpa_s |wpa_supplicant| struct corresponding to the interface.
+ * @param code Deauth reason code sent from server.
+ * @param reauth_delay Reauthentication delay in seconds sent from server.
+ * @param url URL of the server.
+ */
+void HidlManager::notifyHs20RxDeauthImminentNotice(
+    struct wpa_supplicant *wpa_s, u8 code, u16 reauth_delay, const char *url)
+{
+	if (!wpa_s || !url)
+		return;
+
+	if (sta_iface_object_map_.find(wpa_s->ifname) ==
+	    sta_iface_object_map_.end())
+		return;
+
+	callWithEachStaIfaceCallback(
+	    wpa_s->ifname,
+	    std::bind(
+		&ISupplicantStaIfaceCallback::onHs20DeauthImminentNotice,
+		std::placeholders::_1, wpa_s->bssid, code, reauth_delay, url));
+}
+
+/**
+ * Notify all listeners about the reason code for disconnection from the
+ * currently connected network.
+ *
+ * @param wpa_s |wpa_supplicant| struct corresponding to the interface on which
+ * the network is present.
+ */
+void HidlManager::notifyDisconnectReason(struct wpa_supplicant *wpa_s)
+{
+	if (!wpa_s)
+		return;
+
+	if (sta_iface_object_map_.find(wpa_s->ifname) ==
+	    sta_iface_object_map_.end())
+		return;
+
+	const u8 *bssid = wpa_s->bssid;
+	if (is_zero_ether_addr(bssid)) {
+		bssid = wpa_s->pending_bssid;
+	}
+
+	callWithEachStaIfaceCallback(
+	    wpa_s->ifname,
+	    std::bind(
+		&ISupplicantStaIfaceCallback::onDisconnected,
+		std::placeholders::_1, bssid, wpa_s->disconnect_reason < 0,
+		static_cast<ISupplicantStaIfaceCallback::ReasonCode>(
+		    abs(wpa_s->disconnect_reason))));
+}
+
+/**
+ * Notify all listeners about association reject from the access point to which
+ * we are attempting to connect.
+ *
+ * @param wpa_s |wpa_supplicant| struct corresponding to the interface on which
+ * the network is present.
+ */
+void HidlManager::notifyAssocReject(struct wpa_supplicant *wpa_s)
+{
+	if (!wpa_s)
+		return;
+
+	if (sta_iface_object_map_.find(wpa_s->ifname) ==
+	    sta_iface_object_map_.end())
+		return;
+
+	const u8 *bssid = wpa_s->bssid;
+	if (is_zero_ether_addr(bssid)) {
+		bssid = wpa_s->pending_bssid;
+	}
+
+	callWithEachStaIfaceCallback(
+	    wpa_s->ifname,
+	    std::bind(
+		&ISupplicantStaIfaceCallback::onAssociationRejected,
+		std::placeholders::_1, bssid,
+		static_cast<ISupplicantStaIfaceCallback::StatusCode>(
+		    wpa_s->assoc_status_code),
+		wpa_s->assoc_timed_out == 1));
+}
+
+void HidlManager::notifyAuthTimeout(struct wpa_supplicant *wpa_s)
+{
+	if (!wpa_s)
+		return;
+
+	const std::string ifname(wpa_s->ifname);
+	if (sta_iface_object_map_.find(ifname) == sta_iface_object_map_.end())
+		return;
+
+	const u8 *bssid = wpa_s->bssid;
+	if (is_zero_ether_addr(bssid)) {
+		bssid = wpa_s->pending_bssid;
+	}
+	callWithEachStaIfaceCallback(
+	    wpa_s->ifname,
+	    std::bind(
+		&ISupplicantStaIfaceCallback::onAuthenticationTimeout,
+		std::placeholders::_1, bssid));
+}
+
+void HidlManager::notifyBssidChanged(struct wpa_supplicant *wpa_s)
+{
+	if (!wpa_s)
+		return;
+
+	const std::string ifname(wpa_s->ifname);
+	if (sta_iface_object_map_.find(ifname) == sta_iface_object_map_.end())
+		return;
+
+	// wpa_supplicant does not explicitly give us the reason for bssid
+	// change, but we figure that out from what is set out of |wpa_s->bssid|
+	// & |wpa_s->pending_bssid|.
+	const u8 *bssid;
+	ISupplicantStaIfaceCallback::BssidChangeReason reason;
+	if (is_zero_ether_addr(wpa_s->bssid) &&
+	    !is_zero_ether_addr(wpa_s->pending_bssid)) {
+		bssid = wpa_s->pending_bssid;
+		reason =
+		    ISupplicantStaIfaceCallback::BssidChangeReason::ASSOC_START;
+	} else if (
+	    !is_zero_ether_addr(wpa_s->bssid) &&
+	    is_zero_ether_addr(wpa_s->pending_bssid)) {
+		bssid = wpa_s->bssid;
+		reason = ISupplicantStaIfaceCallback::BssidChangeReason::
+		    ASSOC_COMPLETE;
+	} else if (
+	    is_zero_ether_addr(wpa_s->bssid) &&
+	    is_zero_ether_addr(wpa_s->pending_bssid)) {
+		bssid = wpa_s->pending_bssid;
+		reason =
+		    ISupplicantStaIfaceCallback::BssidChangeReason::DISASSOC;
+	} else {
+		wpa_printf(MSG_ERROR, "Unknown bssid change reason");
+		return;
+	}
+
+	callWithEachStaIfaceCallback(
+	    wpa_s->ifname, std::bind(
+			       &ISupplicantStaIfaceCallback::onBssidChanged,
+			       std::placeholders::_1, reason, bssid));
+}
+
+void HidlManager::notifyWpsEventFail(
+    struct wpa_supplicant *wpa_s, uint8_t *peer_macaddr, uint16_t config_error,
+    uint16_t error_indication)
+{
+	if (!wpa_s || !peer_macaddr)
+		return;
+
+	if (sta_iface_object_map_.find(wpa_s->ifname) ==
+	    sta_iface_object_map_.end())
+		return;
+
+	callWithEachStaIfaceCallback(
+	    wpa_s->ifname,
+	    std::bind(
+		&ISupplicantStaIfaceCallback::onWpsEventFail,
+		std::placeholders::_1, peer_macaddr,
+		static_cast<ISupplicantStaIfaceCallback::WpsConfigError>(
+		    config_error),
+		static_cast<ISupplicantStaIfaceCallback::WpsErrorIndication>(
+		    error_indication)));
+}
+
+void HidlManager::notifyWpsEventSuccess(struct wpa_supplicant *wpa_s)
+{
+	if (!wpa_s)
+		return;
+
+	if (sta_iface_object_map_.find(wpa_s->ifname) ==
+	    sta_iface_object_map_.end())
+		return;
+
+	callWithEachStaIfaceCallback(
+	    wpa_s->ifname, std::bind(
+			       &ISupplicantStaIfaceCallback::onWpsEventSuccess,
+			       std::placeholders::_1));
+}
+
+void HidlManager::notifyWpsEventPbcOverlap(struct wpa_supplicant *wpa_s)
+{
+	if (!wpa_s)
+		return;
+
+	if (sta_iface_object_map_.find(wpa_s->ifname) ==
+	    sta_iface_object_map_.end())
+		return;
+
+	callWithEachStaIfaceCallback(
+	    wpa_s->ifname,
+	    std::bind(
+		&ISupplicantStaIfaceCallback::onWpsEventPbcOverlap,
+		std::placeholders::_1));
+}
+
+void HidlManager::notifyP2pDeviceFound(
+    struct wpa_supplicant *wpa_s, const u8 *addr,
+    const struct p2p_peer_info *info, const u8 *peer_wfd_device_info,
+    u8 peer_wfd_device_info_len)
+{
+	if (!wpa_s || !addr || !info)
+		return;
+
+	if (p2p_iface_object_map_.find(wpa_s->ifname) ==
+	    p2p_iface_object_map_.end())
+		return;
+
+	std::array<uint8_t, kWfdDeviceInfoLen> hidl_peer_wfd_device_info{};
+	if (peer_wfd_device_info) {
+		if (peer_wfd_device_info_len != kWfdDeviceInfoLen) {
+			wpa_printf(
+			    MSG_ERROR, "Unexpected WFD device info len: %d",
+			    peer_wfd_device_info_len);
+		} else {
+			os_memcpy(
+			    hidl_peer_wfd_device_info.data(),
+			    peer_wfd_device_info, kWfdDeviceInfoLen);
+		}
+	}
+
+	callWithEachP2pIfaceCallback(
+	    wpa_s->ifname,
+	    std::bind(
+		&ISupplicantP2pIfaceCallback::onDeviceFound,
+		std::placeholders::_1, addr, info->p2p_device_addr,
+		info->pri_dev_type, info->device_name, info->config_methods,
+		info->dev_capab, info->group_capab, hidl_peer_wfd_device_info));
+}
+
+void HidlManager::notifyP2pDeviceLost(
+    struct wpa_supplicant *wpa_s, const u8 *p2p_device_addr)
+{
+	if (!wpa_s || !p2p_device_addr)
+		return;
+
+	if (p2p_iface_object_map_.find(wpa_s->ifname) ==
+	    p2p_iface_object_map_.end())
+		return;
+
+	callWithEachP2pIfaceCallback(
+	    wpa_s->ifname, std::bind(
+			       &ISupplicantP2pIfaceCallback::onDeviceLost,
+			       std::placeholders::_1, p2p_device_addr));
+}
+
+void HidlManager::notifyP2pFindStopped(struct wpa_supplicant *wpa_s)
+{
+	if (!wpa_s)
+		return;
+
+	if (p2p_iface_object_map_.find(wpa_s->ifname) ==
+	    p2p_iface_object_map_.end())
+		return;
+
+	callWithEachP2pIfaceCallback(
+	    wpa_s->ifname, std::bind(
+			       &ISupplicantP2pIfaceCallback::onFindStopped,
+			       std::placeholders::_1));
+}
+
+void HidlManager::notifyP2pGoNegReq(
+    struct wpa_supplicant *wpa_s, const u8 *src_addr, u16 dev_passwd_id,
+    u8 /* go_intent */)
+{
+	if (!wpa_s || !src_addr)
+		return;
+
+	if (p2p_iface_object_map_.find(wpa_s->ifname) ==
+	    p2p_iface_object_map_.end())
+		return;
+
+	callWithEachP2pIfaceCallback(
+	    wpa_s->ifname,
+	    std::bind(
+		&ISupplicantP2pIfaceCallback::onGoNegotiationRequest,
+		std::placeholders::_1, src_addr,
+		static_cast<ISupplicantP2pIfaceCallback::WpsDevPasswordId>(
+		    dev_passwd_id)));
+}
+
+void HidlManager::notifyP2pGoNegCompleted(
+    struct wpa_supplicant *wpa_s, const struct p2p_go_neg_results *res)
+{
+	if (!wpa_s || !res)
+		return;
+
+	if (p2p_iface_object_map_.find(wpa_s->ifname) ==
+	    p2p_iface_object_map_.end())
+		return;
+
+	callWithEachP2pIfaceCallback(
+	    wpa_s->ifname,
+	    std::bind(
+		&ISupplicantP2pIfaceCallback::onGoNegotiationCompleted,
+		std::placeholders::_1,
+		static_cast<ISupplicantP2pIfaceCallback::P2pStatusCode>(
+		    res->status)));
+}
+
+void HidlManager::notifyP2pGroupFormationFailure(
+    struct wpa_supplicant *wpa_s, const char *reason)
+{
+	if (!wpa_s || !reason)
+		return;
+
+	if (p2p_iface_object_map_.find(wpa_s->ifname) ==
+	    p2p_iface_object_map_.end())
+		return;
+
+	callWithEachP2pIfaceCallback(
+	    wpa_s->ifname,
+	    std::bind(
+		&ISupplicantP2pIfaceCallback::onGroupFormationFailure,
+		std::placeholders::_1, reason));
+}
+
+void HidlManager::notifyP2pGroupStarted(
+    struct wpa_supplicant *wpa_group_s, const struct wpa_ssid *ssid, int persistent, int client)
+{
+	if (!wpa_group_s || !wpa_group_s->parent || !ssid)
+		return;
+
+	// For group notifications, need to use the parent iface for callbacks.
+	struct wpa_supplicant *wpa_s = wpa_group_s->parent;
+	if (p2p_iface_object_map_.find(wpa_s->ifname) ==
+	    p2p_iface_object_map_.end())
+		return;
+
+	uint32_t hidl_freq = wpa_group_s->current_bss
+				 ? wpa_group_s->current_bss->freq
+				 : wpa_group_s->assoc_freq;
+	std::array<uint8_t, 32> hidl_psk;
+	if (ssid->psk_set) {
+		os_memcpy(hidl_psk.data(), ssid->psk, 32);
+	}
+	bool hidl_is_go = (client == 0 ? true : false);
+	bool hidl_is_persistent = (persistent == 1 ? true : false);
+
+	callWithEachP2pIfaceCallback(
+	    wpa_s->ifname,
+	    std::bind(
+		&ISupplicantP2pIfaceCallback::onGroupStarted,
+		std::placeholders::_1, wpa_group_s->ifname, hidl_is_go,
+		std::vector<uint8_t>{ssid->ssid, ssid->ssid + ssid->ssid_len},
+		hidl_freq, hidl_psk, ssid->passphrase, wpa_group_s->go_dev_addr,
+		hidl_is_persistent));
+}
+
+void HidlManager::notifyP2pGroupRemoved(
+    struct wpa_supplicant *wpa_group_s, const struct wpa_ssid *ssid,
+    const char *role)
+{
+	if (!wpa_group_s || !wpa_group_s->parent || !ssid || !role)
+		return;
+
+	// For group notifications, need to use the parent iface for callbacks.
+	struct wpa_supplicant *wpa_s = wpa_group_s->parent;
+	if (p2p_iface_object_map_.find(wpa_s->ifname) ==
+	    p2p_iface_object_map_.end())
+		return;
+
+	bool hidl_is_go = (std::string(role) == "GO");
+
+	callWithEachP2pIfaceCallback(
+	    wpa_s->ifname,
+	    std::bind(
+		&ISupplicantP2pIfaceCallback::onGroupRemoved,
+		std::placeholders::_1, wpa_group_s->ifname, hidl_is_go));
+}
+
+void HidlManager::notifyP2pInvitationReceived(
+    struct wpa_supplicant *wpa_s, const u8 *sa, const u8 *go_dev_addr,
+    const u8 *bssid, int id, int op_freq)
+{
+	if (!wpa_s || !sa || !go_dev_addr || !bssid)
+		return;
+
+	if (p2p_iface_object_map_.find(wpa_s->ifname) ==
+	    p2p_iface_object_map_.end())
+		return;
+
+	SupplicantNetworkId hidl_network_id;
+	if (id < 0) {
+		hidl_network_id = UINT32_MAX;
+	}
+	hidl_network_id = id;
+
+	callWithEachP2pIfaceCallback(
+	    wpa_s->ifname,
+	    std::bind(
+		&ISupplicantP2pIfaceCallback::onInvitationReceived,
+		std::placeholders::_1, sa, go_dev_addr, bssid, hidl_network_id,
+		op_freq));
+}
+
+void HidlManager::notifyP2pInvitationResult(
+    struct wpa_supplicant *wpa_s, int status, const u8 *bssid)
+{
+	if (!wpa_s)
+		return;
+
+	if (p2p_iface_object_map_.find(wpa_s->ifname) ==
+	    p2p_iface_object_map_.end())
+		return;
+
+	callWithEachP2pIfaceCallback(
+	    wpa_s->ifname,
+	    std::bind(
+		&ISupplicantP2pIfaceCallback::onInvitationResult,
+		std::placeholders::_1, bssid ? bssid : kZeroBssid,
+		static_cast<ISupplicantP2pIfaceCallback::P2pStatusCode>(
+		    status)));
+}
+
+void HidlManager::notifyP2pProvisionDiscovery(
+    struct wpa_supplicant *wpa_s, const u8 *dev_addr, int request,
+    enum p2p_prov_disc_status status, u16 config_methods,
+    unsigned int generated_pin)
+{
+	if (!wpa_s || !dev_addr)
+		return;
+
+	if (p2p_iface_object_map_.find(wpa_s->ifname) ==
+	    p2p_iface_object_map_.end())
+		return;
+
+	std::string hidl_generated_pin;
+	if (generated_pin > 0) {
+		hidl_generated_pin =
+		    misc_utils::convertWpsPinToString(generated_pin);
+	}
+	bool hidl_is_request = (request == 1 ? true : false);
+
+	callWithEachP2pIfaceCallback(
+	    wpa_s->ifname,
+	    std::bind(
+		&ISupplicantP2pIfaceCallback::onProvisionDiscoveryCompleted,
+		std::placeholders::_1, dev_addr, hidl_is_request,
+		static_cast<ISupplicantP2pIfaceCallback::P2pProvDiscStatusCode>(
+		    status),
+		config_methods, hidl_generated_pin));
+}
+
+void HidlManager::notifyP2pSdResponse(
+    struct wpa_supplicant *wpa_s, const u8 *sa, u16 update_indic,
+    const u8 *tlvs, size_t tlvs_len)
+{
+	if (!wpa_s || !sa || !tlvs)
+		return;
+
+	if (p2p_iface_object_map_.find(wpa_s->ifname) ==
+	    p2p_iface_object_map_.end())
+		return;
+
+	callWithEachP2pIfaceCallback(
+	    wpa_s->ifname,
+	    std::bind(
+		&ISupplicantP2pIfaceCallback::onServiceDiscoveryResponse,
+		std::placeholders::_1, sa, update_indic,
+		std::vector<uint8_t>{tlvs, tlvs + tlvs_len}));
+}
+
+void HidlManager::notifyApStaAuthorized(
+    struct wpa_supplicant *wpa_s, const u8 *sta, const u8 *p2p_dev_addr)
+{
+	if (!wpa_s || !wpa_s->parent || !sta)
+		return;
+	if (p2p_iface_object_map_.find(wpa_s->parent->ifname) ==
+	    p2p_iface_object_map_.end())
+		return;
+	callWithEachP2pIfaceCallback(
+	    wpa_s->parent->ifname, std::bind(
+			       &ISupplicantP2pIfaceCallback::onStaAuthorized,
+			       std::placeholders::_1, sta, p2p_dev_addr ? p2p_dev_addr : kZeroBssid));
+}
+
+void HidlManager::notifyApStaDeauthorized(
+    struct wpa_supplicant *wpa_s, const u8 *sta, const u8 *p2p_dev_addr)
+{
+	if (!wpa_s || !wpa_s->parent || !sta)
+		return;
+	if (p2p_iface_object_map_.find(wpa_s->parent->ifname) ==
+	    p2p_iface_object_map_.end())
+		return;
+
+	callWithEachP2pIfaceCallback(
+	    wpa_s->parent->ifname, std::bind(
+			       &ISupplicantP2pIfaceCallback::onStaDeauthorized,
+			       std::placeholders::_1, sta, p2p_dev_addr ? p2p_dev_addr : kZeroBssid));
+}
+
+void HidlManager::notifyExtRadioWorkStart(
+    struct wpa_supplicant *wpa_s, uint32_t id)
+{
+	if (!wpa_s)
+		return;
+
+	if (sta_iface_object_map_.find(wpa_s->ifname) ==
+	    sta_iface_object_map_.end())
+		return;
+
+	callWithEachStaIfaceCallback(
+	    wpa_s->ifname,
+	    std::bind(
+		&ISupplicantStaIfaceCallback::onExtRadioWorkStart,
+		std::placeholders::_1, id));
+}
+
+void HidlManager::notifyExtRadioWorkTimeout(
+    struct wpa_supplicant *wpa_s, uint32_t id)
+{
+	if (!wpa_s)
+		return;
+
+	if (sta_iface_object_map_.find(wpa_s->ifname) ==
+	    sta_iface_object_map_.end())
+		return;
+
+	callWithEachStaIfaceCallback(
+	    wpa_s->ifname,
+	    std::bind(
+		&ISupplicantStaIfaceCallback::onExtRadioWorkTimeout,
+		std::placeholders::_1, id));
+}
+
+void HidlManager::notifyEapError(struct wpa_supplicant *wpa_s, int error_code)
+{
+	typedef V1_1::ISupplicantStaIfaceCallback::EapErrorCode EapErrorCode;
+
+	if (!wpa_s)
+		return;
+
+	switch (static_cast<EapErrorCode>(error_code)) {
+		case EapErrorCode::SIM_GENERAL_FAILURE_AFTER_AUTH:
+		case EapErrorCode::SIM_TEMPORARILY_DENIED:
+		case EapErrorCode::SIM_NOT_SUBSCRIBED:
+		case EapErrorCode::SIM_GENERAL_FAILURE_BEFORE_AUTH:
+		case EapErrorCode::SIM_VENDOR_SPECIFIC_EXPIRED_CERT:
+			break;
+		default:
+			return;
+	}
+
+	callWithEachStaIfaceCallback_1_1(
+	    wpa_s->ifname,
+	    std::bind(
+		&V1_1::ISupplicantStaIfaceCallback::onEapFailure_1_1,
+		std::placeholders::_1,
+		static_cast<EapErrorCode>(error_code)));
+}
+
+/**
+ * Retrieve the |ISupplicantP2pIface| 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::getP2pIfaceHidlObjectByIfname(
+    const std::string &ifname, android::sp<ISupplicantP2pIface> *iface_object)
+{
+	if (ifname.empty() || !iface_object)
+		return 1;
+
+	auto iface_object_iter = p2p_iface_object_map_.find(ifname);
+	if (iface_object_iter == p2p_iface_object_map_.end())
+		return 1;
+
+	*iface_object = iface_object_iter->second;
+	return 0;
+}
+
+/**
+ * Retrieve the |ISupplicantStaIface| 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::getStaIfaceHidlObjectByIfname(
+    const std::string &ifname, android::sp<ISupplicantStaIface> *iface_object)
+{
+	if (ifname.empty() || !iface_object)
+		return 1;
+
+	auto iface_object_iter = sta_iface_object_map_.find(ifname);
+	if (iface_object_iter == sta_iface_object_map_.end())
+		return 1;
+
+	*iface_object = iface_object_iter->second;
+	return 0;
+}
+
+/**
+ * Retrieve the |ISupplicantP2pNetwork| 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::getP2pNetworkHidlObjectByIfnameAndNetworkId(
+    const std::string &ifname, int network_id,
+    android::sp<ISupplicantP2pNetwork> *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 = p2p_network_object_map_.find(network_key);
+	if (network_object_iter == p2p_network_object_map_.end())
+		return 1;
+
+	*network_object = network_object_iter->second;
+	return 0;
+}
+
+/**
+ * Retrieve the |ISupplicantStaNetwork| 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::getStaNetworkHidlObjectByIfnameAndNetworkId(
+    const std::string &ifname, int network_id,
+    android::sp<ISupplicantStaNetwork> *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 = sta_network_object_map_.find(network_key);
+	if (network_object_iter == sta_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<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<
+	    ISupplicantCallback>(
+	    callback, on_hidl_died_fctor, supplicant_callbacks_);
+}
+
+/**
+ * Add a new iface callback hidl object reference to our
+ * interface callback list.
+ *
+ * @param ifname Name of the corresponding interface.
+ * @param callback Hidl reference of the callback object.
+ *
+ * @return 0 on success, 1 on failure.
+ */
+int HidlManager::addP2pIfaceCallbackHidlObject(
+    const std::string &ifname,
+    const android::sp<ISupplicantP2pIfaceCallback> &callback)
+{
+	const std::function<void(
+	    const android::sp<ISupplicantP2pIfaceCallback> &)>
+	    on_hidl_died_fctor = std::bind(
+		&HidlManager::removeP2pIfaceCallbackHidlObject, this, ifname,
+		std::placeholders::_1);
+	return addIfaceCallbackHidlObjectToMap(
+	    ifname, callback, on_hidl_died_fctor, p2p_iface_callbacks_map_);
+}
+
+/**
+ * Add a new iface callback hidl object reference to our
+ * interface callback list.
+ *
+ * @param ifname Name of the corresponding interface.
+ * @param callback Hidl reference of the callback object.
+ *
+ * @return 0 on success, 1 on failure.
+ */
+int HidlManager::addStaIfaceCallbackHidlObject(
+    const std::string &ifname,
+    const android::sp<ISupplicantStaIfaceCallback> &callback)
+{
+	const std::function<void(
+	    const android::sp<ISupplicantStaIfaceCallback> &)>
+	    on_hidl_died_fctor = std::bind(
+		&HidlManager::removeStaIfaceCallbackHidlObject, this, ifname,
+		std::placeholders::_1);
+	return addIfaceCallbackHidlObjectToMap(
+	    ifname, callback, on_hidl_died_fctor, sta_iface_callbacks_map_);
+}
+
+/**
+ * Add a new network callback 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 callback object.
+ *
+ * @return 0 on success, 1 on failure.
+ */
+int HidlManager::addP2pNetworkCallbackHidlObject(
+    const std::string &ifname, int network_id,
+    const android::sp<ISupplicantP2pNetworkCallback> &callback)
+{
+	const std::function<void(
+	    const android::sp<ISupplicantP2pNetworkCallback> &)>
+	    on_hidl_died_fctor = std::bind(
+		&HidlManager::removeP2pNetworkCallbackHidlObject, this, ifname,
+		network_id, std::placeholders::_1);
+	return addNetworkCallbackHidlObjectToMap(
+	    ifname, network_id, callback, on_hidl_died_fctor,
+	    p2p_network_callbacks_map_);
+}
+
+/**
+ * Add a new network callback 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 callback object.
+ *
+ * @return 0 on success, 1 on failure.
+ */
+int HidlManager::addStaNetworkCallbackHidlObject(
+    const std::string &ifname, int network_id,
+    const android::sp<ISupplicantStaNetworkCallback> &callback)
+{
+	const std::function<void(
+	    const android::sp<ISupplicantStaNetworkCallback> &)>
+	    on_hidl_died_fctor = std::bind(
+		&HidlManager::removeStaNetworkCallbackHidlObject, this, ifname,
+		network_id, std::placeholders::_1);
+	return addNetworkCallbackHidlObjectToMap(
+	    ifname, network_id, callback, on_hidl_died_fctor,
+	    sta_network_callbacks_map_);
+}
+
+/**
+ * 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<ISupplicantCallback> &callback)
+{
+	supplicant_callbacks_.erase(
+	    std::remove(
+		supplicant_callbacks_.begin(), supplicant_callbacks_.end(),
+		callback),
+	    supplicant_callbacks_.end());
+}
+
+/**
+ * Removes the provided iface callback hidl object reference from
+ * our interface callback list.
+ *
+ * @param ifname Name of the corresponding interface.
+ * @param callback Hidl reference of the callback object.
+ */
+void HidlManager::removeP2pIfaceCallbackHidlObject(
+    const std::string &ifname,
+    const android::sp<ISupplicantP2pIfaceCallback> &callback)
+{
+	return removeIfaceCallbackHidlObjectFromMap(
+	    ifname, callback, p2p_iface_callbacks_map_);
+}
+
+/**
+ * Removes the provided iface callback hidl object reference from
+ * our interface callback list.
+ *
+ * @param ifname Name of the corresponding interface.
+ * @param callback Hidl reference of the callback object.
+ */
+void HidlManager::removeStaIfaceCallbackHidlObject(
+    const std::string &ifname,
+    const android::sp<ISupplicantStaIfaceCallback> &callback)
+{
+	return removeIfaceCallbackHidlObjectFromMap(
+	    ifname, callback, sta_iface_callbacks_map_);
+}
+
+/**
+ * Removes the provided network callback 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 callback object.
+ */
+void HidlManager::removeP2pNetworkCallbackHidlObject(
+    const std::string &ifname, int network_id,
+    const android::sp<ISupplicantP2pNetworkCallback> &callback)
+{
+	return removeNetworkCallbackHidlObjectFromMap(
+	    ifname, network_id, callback, p2p_network_callbacks_map_);
+}
+
+/**
+ * Removes the provided network callback 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 callback object.
+ */
+void HidlManager::removeStaNetworkCallbackHidlObject(
+    const std::string &ifname, int network_id,
+    const android::sp<ISupplicantStaNetworkCallback> &callback)
+{
+	return removeNetworkCallbackHidlObjectFromMap(
+	    ifname, network_id, callback, sta_network_callbacks_map_);
+}
+
+/**
+ * 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<Return<void>(android::sp<ISupplicantCallback>)> &method)
+{
+	for (const auto &callback : supplicant_callbacks_) {
+		if (!method(callback).isOk()) {
+			wpa_printf(MSG_ERROR, "Failed to invoke HIDL callback");
+		}
+	}
+}
+
+/**
+ * Helper fucntion to invoke the provided callback method on all the
+ * registered iface callback hidl objects for the specified
+ * |ifname|.
+ *
+ * @param ifname Name of the corresponding interface.
+ * @param method Pointer to the required hidl method from
+ * |ISupplicantIfaceCallback|.
+ */
+void HidlManager::callWithEachP2pIfaceCallback(
+    const std::string &ifname,
+    const std::function<Return<void>(android::sp<ISupplicantP2pIfaceCallback>)>
+	&method)
+{
+	callWithEachIfaceCallback(ifname, method, p2p_iface_callbacks_map_);
+}
+
+/**
+ * Helper fucntion to invoke the provided callback method on all the
+ * registered V1.1 iface callback hidl objects for the specified
+ * |ifname|.
+ *
+ * @param ifname Name of the corresponding interface.
+ * @param method Pointer to the required hidl method from
+ * |V1_1::ISupplicantIfaceCallback|.
+ */
+void HidlManager::callWithEachStaIfaceCallback_1_1(
+    const std::string &ifname,
+    const std::function<Return<void>
+	(android::sp<V1_1::ISupplicantStaIfaceCallback>)> &method)
+{
+	callWithEachIfaceCallback_1_1(ifname, method, sta_iface_callbacks_map_);
+}
+
+/**
+ * Helper fucntion to invoke the provided callback method on all the
+ * registered iface callback hidl objects for the specified
+ * |ifname|.
+ *
+ * @param ifname Name of the corresponding interface.
+ * @param method Pointer to the required hidl method from
+ * |ISupplicantIfaceCallback|.
+ */
+void HidlManager::callWithEachStaIfaceCallback(
+    const std::string &ifname,
+    const std::function<Return<void>(android::sp<ISupplicantStaIfaceCallback>)>
+	&method)
+{
+	callWithEachIfaceCallback(ifname, method, sta_iface_callbacks_map_);
+}
+
+/**
+ * Helper function to invoke the provided callback method on all the
+ * registered network 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
+ * |ISupplicantP2pNetworkCallback| or |ISupplicantStaNetworkCallback| .
+ */
+void HidlManager::callWithEachP2pNetworkCallback(
+    const std::string &ifname, int network_id,
+    const std::function<
+	Return<void>(android::sp<ISupplicantP2pNetworkCallback>)> &method)
+{
+	callWithEachNetworkCallback(
+	    ifname, network_id, method, p2p_network_callbacks_map_);
+}
+
+/**
+ * Helper function to invoke the provided callback method on all the
+ * registered network 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
+ * |ISupplicantP2pNetworkCallback| or |ISupplicantStaNetworkCallback| .
+ */
+void HidlManager::callWithEachStaNetworkCallback(
+    const std::string &ifname, int network_id,
+    const std::function<
+	Return<void>(android::sp<ISupplicantStaNetworkCallback>)> &method)
+{
+	callWithEachNetworkCallback(
+	    ifname, network_id, method, sta_network_callbacks_map_);
+}
+}  // namespace implementation
+}  // namespace V1_1
+}  // namespace wifi
+}  // namespace supplicant
+}  // namespace hardware
+}  // namespace android
diff --git a/wpa_supplicant/hidl/1.1/hidl_manager.h b/wpa_supplicant/hidl/1.1/hidl_manager.h
new file mode 100644
index 0000000..4f100aa
--- /dev/null
+++ b/wpa_supplicant/hidl/1.1/hidl_manager.h
@@ -0,0 +1,687 @@
+/*
+ * 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 <android/hardware/wifi/supplicant/1.0/ISupplicantCallback.h>
+#include <android/hardware/wifi/supplicant/1.0/ISupplicantP2pIfaceCallback.h>
+#include <android/hardware/wifi/supplicant/1.0/ISupplicantP2pNetworkCallback.h>
+#include <android/hardware/wifi/supplicant/1.1/ISupplicantStaIfaceCallback.h>
+#include <android/hardware/wifi/supplicant/1.0/ISupplicantStaNetworkCallback.h>
+
+#include "p2p_iface.h"
+#include "p2p_network.h"
+#include "sta_iface.h"
+#include "sta_network.h"
+#include "supplicant.h"
+
+extern "C" {
+#include "utils/common.h"
+#include "utils/includes.h"
+#include "wpa_supplicant_i.h"
+#include "driver_i.h"
+}
+
+namespace android {
+namespace hardware {
+namespace wifi {
+namespace supplicant {
+namespace V1_1 {
+namespace implementation {
+using namespace android::hardware::wifi::supplicant::V1_0;
+using namespace android::hardware::wifi::supplicant::V1_1;
+using V1_0::ISupplicantStaIfaceCallback;
+
+/**
+ * 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);
+	void notifyAnqpQueryDone(
+	    struct wpa_supplicant *wpa_s, const u8 *bssid, const char *result,
+	    const struct wpa_bss_anqp *anqp);
+	void notifyHs20IconQueryDone(
+	    struct wpa_supplicant *wpa_s, const u8 *bssid,
+	    const char *file_name, const u8 *image, u32 image_length);
+	void notifyHs20RxSubscriptionRemediation(
+	    struct wpa_supplicant *wpa_s, const char *url, u8 osu_method);
+	void notifyHs20RxDeauthImminentNotice(
+	    struct wpa_supplicant *wpa_s, u8 code, u16 reauth_delay,
+	    const char *url);
+	void notifyDisconnectReason(struct wpa_supplicant *wpa_s);
+	void notifyAssocReject(struct wpa_supplicant *wpa_s);
+	void notifyAuthTimeout(struct wpa_supplicant *wpa_s);
+	void notifyBssidChanged(struct wpa_supplicant *wpa_s);
+	void notifyWpsEventFail(
+	    struct wpa_supplicant *wpa_s, uint8_t *peer_macaddr,
+	    uint16_t config_error, uint16_t error_indication);
+	void notifyWpsEventSuccess(struct wpa_supplicant *wpa_s);
+	void notifyWpsEventPbcOverlap(struct wpa_supplicant *wpa_s);
+	void notifyP2pDeviceFound(
+	    struct wpa_supplicant *wpa_s, const u8 *addr,
+	    const struct p2p_peer_info *info, const u8 *peer_wfd_device_info,
+	    u8 peer_wfd_device_info_len);
+	void notifyP2pDeviceLost(
+	    struct wpa_supplicant *wpa_s, const u8 *p2p_device_addr);
+	void notifyP2pFindStopped(struct wpa_supplicant *wpa_s);
+	void notifyP2pGoNegReq(
+	    struct wpa_supplicant *wpa_s, const u8 *src_addr, u16 dev_passwd_id,
+	    u8 go_intent);
+	void notifyP2pGoNegCompleted(
+	    struct wpa_supplicant *wpa_s, const struct p2p_go_neg_results *res);
+	void notifyP2pGroupFormationFailure(
+	    struct wpa_supplicant *wpa_s, const char *reason);
+	void notifyP2pGroupStarted(
+	    struct wpa_supplicant *wpa_group_s, const struct wpa_ssid *ssid,
+	    int persistent, int client);
+	void notifyP2pGroupRemoved(
+	    struct wpa_supplicant *wpa_group_s, const struct wpa_ssid *ssid,
+	    const char *role);
+	void notifyP2pInvitationReceived(
+	    struct wpa_supplicant *wpa_s, const u8 *sa, const u8 *go_dev_addr,
+	    const u8 *bssid, int id, int op_freq);
+	void notifyP2pInvitationResult(
+	    struct wpa_supplicant *wpa_s, int status, const u8 *bssid);
+	void notifyP2pProvisionDiscovery(
+	    struct wpa_supplicant *wpa_s, const u8 *dev_addr, int request,
+	    enum p2p_prov_disc_status status, u16 config_methods,
+	    unsigned int generated_pin);
+	void notifyP2pSdResponse(
+	    struct wpa_supplicant *wpa_s, const u8 *sa, u16 update_indic,
+	    const u8 *tlvs, size_t tlvs_len);
+	void notifyApStaAuthorized(
+	    struct wpa_supplicant *wpa_s, const u8 *sta,
+	    const u8 *p2p_dev_addr);
+	void notifyApStaDeauthorized(
+	    struct wpa_supplicant *wpa_s, const u8 *sta,
+	    const u8 *p2p_dev_addr);
+	void notifyEapError(
+	    struct wpa_supplicant *wpa_s, int error_code);
+
+	// Methods called from hidl objects.
+	void notifyExtRadioWorkStart(struct wpa_supplicant *wpa_s, uint32_t id);
+	void notifyExtRadioWorkTimeout(
+	    struct wpa_supplicant *wpa_s, uint32_t id);
+
+	int getP2pIfaceHidlObjectByIfname(
+	    const std::string &ifname,
+	    android::sp<ISupplicantP2pIface> *iface_object);
+	int getStaIfaceHidlObjectByIfname(
+	    const std::string &ifname,
+	    android::sp<ISupplicantStaIface> *iface_object);
+	int getP2pNetworkHidlObjectByIfnameAndNetworkId(
+	    const std::string &ifname, int network_id,
+	    android::sp<ISupplicantP2pNetwork> *network_object);
+	int getStaNetworkHidlObjectByIfnameAndNetworkId(
+	    const std::string &ifname, int network_id,
+	    android::sp<ISupplicantStaNetwork> *network_object);
+	int addSupplicantCallbackHidlObject(
+	    const android::sp<ISupplicantCallback> &callback);
+	int addP2pIfaceCallbackHidlObject(
+	    const std::string &ifname,
+	    const android::sp<ISupplicantP2pIfaceCallback> &callback);
+	int addStaIfaceCallbackHidlObject(
+	    const std::string &ifname,
+	    const android::sp<ISupplicantStaIfaceCallback> &callback);
+	int addP2pNetworkCallbackHidlObject(
+	    const std::string &ifname, int network_id,
+	    const android::sp<ISupplicantP2pNetworkCallback> &callback);
+	int addStaNetworkCallbackHidlObject(
+	    const std::string &ifname, int network_id,
+	    const android::sp<ISupplicantStaNetworkCallback> &callback);
+
+private:
+	HidlManager() = default;
+	~HidlManager() = default;
+	HidlManager(const HidlManager &) = default;
+	HidlManager &operator=(const HidlManager &) = default;
+
+	void removeSupplicantCallbackHidlObject(
+	    const android::sp<ISupplicantCallback> &callback);
+	void removeP2pIfaceCallbackHidlObject(
+	    const std::string &ifname,
+	    const android::sp<ISupplicantP2pIfaceCallback> &callback);
+	void removeStaIfaceCallbackHidlObject(
+	    const std::string &ifname,
+	    const android::sp<ISupplicantStaIfaceCallback> &callback);
+	void removeP2pNetworkCallbackHidlObject(
+	    const std::string &ifname, int network_id,
+	    const android::sp<ISupplicantP2pNetworkCallback> &callback);
+	void removeStaNetworkCallbackHidlObject(
+	    const std::string &ifname, int network_id,
+	    const android::sp<ISupplicantStaNetworkCallback> &callback);
+
+	void callWithEachSupplicantCallback(
+	    const std::function<android::hardware::Return<void>(
+		android::sp<ISupplicantCallback>)> &method);
+	void callWithEachP2pIfaceCallback(
+	    const std::string &ifname,
+	    const std::function<android::hardware::Return<void>(
+		android::sp<ISupplicantP2pIfaceCallback>)> &method);
+	void callWithEachStaIfaceCallback(
+	    const std::string &ifname,
+	    const std::function<android::hardware::Return<void>(
+		android::sp<ISupplicantStaIfaceCallback>)> &method);
+	void callWithEachStaIfaceCallback_1_1(
+	    const std::string &ifname,
+	    const std::function<android::hardware::Return<void>(
+		android::sp<V1_1::ISupplicantStaIfaceCallback>)> &method);
+	void callWithEachP2pNetworkCallback(
+	    const std::string &ifname, int network_id,
+	    const std::function<android::hardware::Return<void>(
+		android::sp<ISupplicantP2pNetworkCallback>)> &method);
+	void callWithEachStaNetworkCallback(
+	    const std::string &ifname, int network_id,
+	    const std::function<android::hardware::Return<void>(
+		android::sp<ISupplicantStaNetworkCallback>)> &method);
+
+	// Singleton instance of this class.
+	static HidlManager *instance_;
+	// The main hidl service object.
+	android::sp<Supplicant> supplicant_object_;
+	// Map of all the P2P interface specific hidl objects controlled by
+	// wpa_supplicant. This map is keyed in by the corresponding
+	// |ifname|.
+	std::map<const std::string, android::sp<P2pIface>>
+	    p2p_iface_object_map_;
+	// Map of all the STA interface specific hidl objects controlled by
+	// wpa_supplicant. This map is keyed in by the corresponding
+	// |ifname|.
+	std::map<const std::string, android::sp<StaIface>>
+	    sta_iface_object_map_;
+	// Map of all the P2P 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<P2pNetwork>>
+	    p2p_network_object_map_;
+	// Map of all the STA 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<StaNetwork>>
+	    sta_network_object_map_;
+
+	// Callback registered for the main hidl service object.
+	std::vector<android::sp<ISupplicantCallback>> supplicant_callbacks_;
+	// Map of all the callbacks registered for P2P 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<ISupplicantP2pIfaceCallback>>>
+	    p2p_iface_callbacks_map_;
+	// Map of all the callbacks registered for STA 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<ISupplicantStaIfaceCallback>>>
+	    sta_iface_callbacks_map_;
+	// Map of all the callbacks registered for P2P 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<ISupplicantP2pNetworkCallback>>>
+	    p2p_network_callbacks_map_;
+	// Map of all the callbacks registered for STA 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<ISupplicantStaNetworkCallback>>>
+	    sta_network_callbacks_map_;
+
+#if 0  // TODO(b/31632518): HIDL object death notifications.
+	/**
+	 * 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::hardware::IBinder::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 binderDied(const android::wp<android::hardware::IBinder>
+				    & /* 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_;
+	};
+#endif
+};
+
+// 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(
+    static_cast<uint32_t>(ISupplicant::DebugLevel::EXCESSIVE) == MSG_EXCESSIVE,
+    "Debug level value mismatch");
+static_assert(
+    static_cast<uint32_t>(ISupplicant::DebugLevel::ERROR) == MSG_ERROR,
+    "Debug level value mismatch");
+
+static_assert(
+    static_cast<uint32_t>(ISupplicantStaNetwork::KeyMgmtMask::NONE) ==
+	WPA_KEY_MGMT_NONE,
+    "KeyMgmt value mismatch");
+static_assert(
+    static_cast<uint32_t>(ISupplicantStaNetwork::KeyMgmtMask::WPA_PSK) ==
+	WPA_KEY_MGMT_PSK,
+    "KeyMgmt value mismatch");
+static_assert(
+    static_cast<uint32_t>(ISupplicantStaNetwork::KeyMgmtMask::WPA_EAP) ==
+	WPA_KEY_MGMT_IEEE8021X,
+    "KeyMgmt value mismatch");
+static_assert(
+    static_cast<uint32_t>(ISupplicantStaNetwork::KeyMgmtMask::IEEE8021X) ==
+	WPA_KEY_MGMT_IEEE8021X_NO_WPA,
+    "KeyMgmt value mismatch");
+static_assert(
+    static_cast<uint32_t>(ISupplicantStaNetwork::KeyMgmtMask::FT_EAP) ==
+	WPA_KEY_MGMT_FT_IEEE8021X,
+    "KeyMgmt value mismatch");
+static_assert(
+    static_cast<uint32_t>(ISupplicantStaNetwork::KeyMgmtMask::FT_PSK) ==
+	WPA_KEY_MGMT_FT_PSK,
+    "KeyMgmt value mismatch");
+static_assert(
+    static_cast<uint32_t>(ISupplicantStaNetwork::KeyMgmtMask::OSEN) ==
+	WPA_KEY_MGMT_OSEN,
+    "KeyMgmt value mismatch");
+static_assert(
+    static_cast<uint32_t>(ISupplicantStaNetwork::ProtoMask::WPA) ==
+	WPA_PROTO_WPA,
+    "Proto value mismatch");
+static_assert(
+    static_cast<uint32_t>(ISupplicantStaNetwork::ProtoMask::RSN) ==
+	WPA_PROTO_RSN,
+    "Proto value mismatch");
+static_assert(
+    static_cast<uint32_t>(ISupplicantStaNetwork::ProtoMask::OSEN) ==
+	WPA_PROTO_OSEN,
+    "Proto value mismatch");
+static_assert(
+    static_cast<uint32_t>(ISupplicantStaNetwork::AuthAlgMask::OPEN) ==
+	WPA_AUTH_ALG_OPEN,
+    "AuthAlg value mismatch");
+static_assert(
+    static_cast<uint32_t>(ISupplicantStaNetwork::AuthAlgMask::SHARED) ==
+	WPA_AUTH_ALG_SHARED,
+    "AuthAlg value mismatch");
+static_assert(
+    static_cast<uint32_t>(ISupplicantStaNetwork::AuthAlgMask::LEAP) ==
+	WPA_AUTH_ALG_LEAP,
+    "AuthAlg value mismatch");
+static_assert(
+    static_cast<uint32_t>(ISupplicantStaNetwork::GroupCipherMask::WEP40) ==
+	WPA_CIPHER_WEP40,
+    "GroupCipher value mismatch");
+static_assert(
+    static_cast<uint32_t>(ISupplicantStaNetwork::GroupCipherMask::WEP104) ==
+	WPA_CIPHER_WEP104,
+    "GroupCipher value mismatch");
+static_assert(
+    static_cast<uint32_t>(ISupplicantStaNetwork::GroupCipherMask::TKIP) ==
+	WPA_CIPHER_TKIP,
+    "GroupCipher value mismatch");
+static_assert(
+    static_cast<uint32_t>(ISupplicantStaNetwork::GroupCipherMask::CCMP) ==
+	WPA_CIPHER_CCMP,
+    "GroupCipher value mismatch");
+static_assert(
+    static_cast<uint32_t>(
+	ISupplicantStaNetwork::GroupCipherMask::GTK_NOT_USED) ==
+	WPA_CIPHER_GTK_NOT_USED,
+    "GroupCipher value mismatch");
+static_assert(
+    static_cast<uint32_t>(ISupplicantStaNetwork::PairwiseCipherMask::NONE) ==
+	WPA_CIPHER_NONE,
+    "PairwiseCipher value mismatch");
+static_assert(
+    static_cast<uint32_t>(ISupplicantStaNetwork::PairwiseCipherMask::TKIP) ==
+	WPA_CIPHER_TKIP,
+    "PairwiseCipher value mismatch");
+static_assert(
+    static_cast<uint32_t>(ISupplicantStaNetwork::PairwiseCipherMask::CCMP) ==
+	WPA_CIPHER_CCMP,
+    "PairwiseCipher value mismatch");
+
+static_assert(
+    static_cast<uint32_t>(ISupplicantStaIfaceCallback::State::DISCONNECTED) ==
+	WPA_DISCONNECTED,
+    "State value mismatch");
+static_assert(
+    static_cast<uint32_t>(ISupplicantStaIfaceCallback::State::COMPLETED) ==
+	WPA_COMPLETED,
+    "State value mismatch");
+
+static_assert(
+    static_cast<uint32_t>(ISupplicantStaIface::AnqpInfoId::VENUE_NAME) ==
+	ANQP_VENUE_NAME,
+    "ANQP ID value mismatch");
+static_assert(
+    static_cast<uint32_t>(
+	ISupplicantStaIface::AnqpInfoId::ROAMING_CONSORTIUM) ==
+	ANQP_ROAMING_CONSORTIUM,
+    "ANQP ID value mismatch");
+static_assert(
+    static_cast<uint32_t>(ISupplicantStaIface::AnqpInfoId::NAI_REALM) ==
+	ANQP_NAI_REALM,
+    "ANQP ID value mismatch");
+static_assert(
+    static_cast<uint32_t>(
+	ISupplicantStaIface::AnqpInfoId::IP_ADDR_TYPE_AVAILABILITY) ==
+	ANQP_IP_ADDR_TYPE_AVAILABILITY,
+    "ANQP ID value mismatch");
+static_assert(
+    static_cast<uint32_t>(
+	ISupplicantStaIface::AnqpInfoId::ANQP_3GPP_CELLULAR_NETWORK) ==
+	ANQP_3GPP_CELLULAR_NETWORK,
+    "ANQP ID value mismatch");
+static_assert(
+    static_cast<uint32_t>(ISupplicantStaIface::AnqpInfoId::DOMAIN_NAME) ==
+	ANQP_DOMAIN_NAME,
+    "ANQP ID value mismatch");
+static_assert(
+    static_cast<uint32_t>(
+	ISupplicantStaIface::Hs20AnqpSubtypes::OPERATOR_FRIENDLY_NAME) ==
+	HS20_STYPE_OPERATOR_FRIENDLY_NAME,
+    "HS Subtype value mismatch");
+static_assert(
+    static_cast<uint32_t>(ISupplicantStaIface::Hs20AnqpSubtypes::WAN_METRICS) ==
+	HS20_STYPE_WAN_METRICS,
+    "HS Subtype value mismatch");
+static_assert(
+    static_cast<uint32_t>(
+	ISupplicantStaIface::Hs20AnqpSubtypes::CONNECTION_CAPABILITY) ==
+	HS20_STYPE_CONNECTION_CAPABILITY,
+    "HS Subtype value mismatch");
+static_assert(
+    static_cast<uint32_t>(
+	ISupplicantStaIface::Hs20AnqpSubtypes::OSU_PROVIDERS_LIST) ==
+	HS20_STYPE_OSU_PROVIDERS_LIST,
+    "HS Subtype value mismatch");
+
+static_assert(
+    static_cast<uint16_t>(
+	ISupplicantStaIfaceCallback::WpsConfigError::NO_ERROR) ==
+	WPS_CFG_NO_ERROR,
+    "Wps config error value mismatch");
+static_assert(
+    static_cast<uint16_t>(ISupplicantStaIfaceCallback::WpsConfigError::
+			      PUBLIC_KEY_HASH_MISMATCH) ==
+	WPS_CFG_PUBLIC_KEY_HASH_MISMATCH,
+    "Wps config error value mismatch");
+static_assert(
+    static_cast<uint16_t>(
+	ISupplicantStaIfaceCallback::WpsErrorIndication::NO_ERROR) ==
+	WPS_EI_NO_ERROR,
+    "Wps error indication value mismatch");
+static_assert(
+    static_cast<uint16_t>(
+	ISupplicantStaIfaceCallback::WpsErrorIndication::AUTH_FAILURE) ==
+	WPS_EI_AUTH_FAILURE,
+    "Wps error indication value mismatch");
+
+static_assert(
+    static_cast<uint32_t>(WpsConfigMethods::USBA) == WPS_CONFIG_USBA,
+    "Wps config value mismatch");
+static_assert(
+    static_cast<uint32_t>(WpsConfigMethods::ETHERNET) == WPS_CONFIG_ETHERNET,
+    "Wps config value mismatch");
+static_assert(
+    static_cast<uint32_t>(WpsConfigMethods::LABEL) == WPS_CONFIG_LABEL,
+    "Wps config value mismatch");
+static_assert(
+    static_cast<uint32_t>(WpsConfigMethods::DISPLAY) == WPS_CONFIG_DISPLAY,
+    "Wps config value mismatch");
+static_assert(
+    static_cast<uint32_t>(WpsConfigMethods::INT_NFC_TOKEN) ==
+	WPS_CONFIG_INT_NFC_TOKEN,
+    "Wps config value mismatch");
+static_assert(
+    static_cast<uint32_t>(WpsConfigMethods::EXT_NFC_TOKEN) ==
+	WPS_CONFIG_EXT_NFC_TOKEN,
+    "Wps config value mismatch");
+static_assert(
+    static_cast<uint32_t>(WpsConfigMethods::NFC_INTERFACE) ==
+	WPS_CONFIG_NFC_INTERFACE,
+    "Wps config value mismatch");
+static_assert(
+    static_cast<uint32_t>(WpsConfigMethods::PUSHBUTTON) ==
+	WPS_CONFIG_PUSHBUTTON,
+    "Wps config value mismatch");
+static_assert(
+    static_cast<uint32_t>(WpsConfigMethods::KEYPAD) == WPS_CONFIG_KEYPAD,
+    "Wps config value mismatch");
+static_assert(
+    static_cast<uint32_t>(WpsConfigMethods::VIRT_PUSHBUTTON) ==
+	WPS_CONFIG_VIRT_PUSHBUTTON,
+    "Wps config value mismatch");
+static_assert(
+    static_cast<uint32_t>(WpsConfigMethods::PHY_PUSHBUTTON) ==
+	WPS_CONFIG_PHY_PUSHBUTTON,
+    "Wps config value mismatch");
+static_assert(
+    static_cast<uint32_t>(WpsConfigMethods::P2PS) == WPS_CONFIG_P2PS,
+    "Wps config value mismatch");
+static_assert(
+    static_cast<uint32_t>(WpsConfigMethods::VIRT_DISPLAY) ==
+	WPS_CONFIG_VIRT_DISPLAY,
+    "Wps config value mismatch");
+static_assert(
+    static_cast<uint32_t>(WpsConfigMethods::PHY_DISPLAY) ==
+	WPS_CONFIG_PHY_DISPLAY,
+    "Wps config value mismatch");
+
+static_assert(
+    static_cast<uint32_t>(P2pGroupCapabilityMask::GROUP_OWNER) ==
+	P2P_GROUP_CAPAB_GROUP_OWNER,
+    "P2P capability value mismatch");
+static_assert(
+    static_cast<uint32_t>(P2pGroupCapabilityMask::PERSISTENT_GROUP) ==
+	P2P_GROUP_CAPAB_PERSISTENT_GROUP,
+    "P2P capability value mismatch");
+static_assert(
+    static_cast<uint32_t>(P2pGroupCapabilityMask::GROUP_LIMIT) ==
+	P2P_GROUP_CAPAB_GROUP_LIMIT,
+    "P2P capability value mismatch");
+static_assert(
+    static_cast<uint32_t>(P2pGroupCapabilityMask::INTRA_BSS_DIST) ==
+	P2P_GROUP_CAPAB_INTRA_BSS_DIST,
+    "P2P capability value mismatch");
+static_assert(
+    static_cast<uint32_t>(P2pGroupCapabilityMask::CROSS_CONN) ==
+	P2P_GROUP_CAPAB_CROSS_CONN,
+    "P2P capability value mismatch");
+static_assert(
+    static_cast<uint32_t>(P2pGroupCapabilityMask::PERSISTENT_RECONN) ==
+	P2P_GROUP_CAPAB_PERSISTENT_RECONN,
+    "P2P capability value mismatch");
+static_assert(
+    static_cast<uint32_t>(P2pGroupCapabilityMask::GROUP_FORMATION) ==
+	P2P_GROUP_CAPAB_GROUP_FORMATION,
+    "P2P capability value mismatch");
+
+static_assert(
+    static_cast<uint16_t>(
+	ISupplicantP2pIfaceCallback::WpsDevPasswordId::DEFAULT) ==
+	DEV_PW_DEFAULT,
+    "Wps dev password id value mismatch");
+static_assert(
+    static_cast<uint16_t>(
+	ISupplicantP2pIfaceCallback::WpsDevPasswordId::USER_SPECIFIED) ==
+	DEV_PW_USER_SPECIFIED,
+    "Wps dev password id value mismatch");
+static_assert(
+    static_cast<uint16_t>(
+	ISupplicantP2pIfaceCallback::WpsDevPasswordId::MACHINE_SPECIFIED) ==
+	DEV_PW_MACHINE_SPECIFIED,
+    "Wps dev password id value mismatch");
+static_assert(
+    static_cast<uint16_t>(
+	ISupplicantP2pIfaceCallback::WpsDevPasswordId::REKEY) == DEV_PW_REKEY,
+    "Wps dev password id value mismatch");
+static_assert(
+    static_cast<uint16_t>(
+	ISupplicantP2pIfaceCallback::WpsDevPasswordId::PUSHBUTTON) ==
+	DEV_PW_PUSHBUTTON,
+    "Wps dev password id value mismatch");
+static_assert(
+    static_cast<uint16_t>(
+	ISupplicantP2pIfaceCallback::WpsDevPasswordId::REGISTRAR_SPECIFIED) ==
+	DEV_PW_REGISTRAR_SPECIFIED,
+    "Wps dev password id value mismatch");
+static_assert(
+    static_cast<uint16_t>(ISupplicantP2pIfaceCallback::WpsDevPasswordId::
+			      NFC_CONNECTION_HANDOVER) ==
+	DEV_PW_NFC_CONNECTION_HANDOVER,
+    "Wps dev password id value mismatch");
+static_assert(
+    static_cast<uint16_t>(
+	ISupplicantP2pIfaceCallback::WpsDevPasswordId::P2PS_DEFAULT) ==
+	DEV_PW_P2PS_DEFAULT,
+    "Wps dev password id value mismatch");
+
+static_assert(
+    static_cast<uint16_t>(
+	ISupplicantP2pIfaceCallback::P2pStatusCode::SUCCESS) == P2P_SC_SUCCESS,
+    "P2P status code value mismatch");
+static_assert(
+    static_cast<uint16_t>(ISupplicantP2pIfaceCallback::P2pStatusCode::
+			      FAIL_INFO_CURRENTLY_UNAVAILABLE) ==
+	P2P_SC_FAIL_INFO_CURRENTLY_UNAVAILABLE,
+    "P2P status code value mismatch");
+static_assert(
+    static_cast<uint16_t>(
+	ISupplicantP2pIfaceCallback::P2pStatusCode::FAIL_INCOMPATIBLE_PARAMS) ==
+	P2P_SC_FAIL_INCOMPATIBLE_PARAMS,
+    "P2P status code value mismatch");
+static_assert(
+    static_cast<uint16_t>(
+	ISupplicantP2pIfaceCallback::P2pStatusCode::FAIL_LIMIT_REACHED) ==
+	P2P_SC_FAIL_LIMIT_REACHED,
+    "P2P status code value mismatch");
+static_assert(
+    static_cast<uint16_t>(
+	ISupplicantP2pIfaceCallback::P2pStatusCode::FAIL_INVALID_PARAMS) ==
+	P2P_SC_FAIL_INVALID_PARAMS,
+    "P2P status code value mismatch");
+static_assert(
+    static_cast<uint16_t>(ISupplicantP2pIfaceCallback::P2pStatusCode::
+			      FAIL_UNABLE_TO_ACCOMMODATE) ==
+	P2P_SC_FAIL_UNABLE_TO_ACCOMMODATE,
+    "P2P status code value mismatch");
+static_assert(
+    static_cast<uint16_t>(
+	ISupplicantP2pIfaceCallback::P2pStatusCode::FAIL_PREV_PROTOCOL_ERROR) ==
+	P2P_SC_FAIL_PREV_PROTOCOL_ERROR,
+    "P2P status code value mismatch");
+static_assert(
+    static_cast<uint16_t>(
+	ISupplicantP2pIfaceCallback::P2pStatusCode::FAIL_NO_COMMON_CHANNELS) ==
+	P2P_SC_FAIL_NO_COMMON_CHANNELS,
+    "P2P status code value mismatch");
+static_assert(
+    static_cast<uint16_t>(
+	ISupplicantP2pIfaceCallback::P2pStatusCode::FAIL_UNKNOWN_GROUP) ==
+	P2P_SC_FAIL_UNKNOWN_GROUP,
+    "P2P status code value mismatch");
+static_assert(
+    static_cast<uint16_t>(
+	ISupplicantP2pIfaceCallback::P2pStatusCode::FAIL_BOTH_GO_INTENT_15) ==
+	P2P_SC_FAIL_BOTH_GO_INTENT_15,
+    "P2P status code value mismatch");
+static_assert(
+    static_cast<uint16_t>(ISupplicantP2pIfaceCallback::P2pStatusCode::
+			      FAIL_INCOMPATIBLE_PROV_METHOD) ==
+	P2P_SC_FAIL_INCOMPATIBLE_PROV_METHOD,
+    "P2P status code value mismatch");
+static_assert(
+    static_cast<uint16_t>(
+	ISupplicantP2pIfaceCallback::P2pStatusCode::FAIL_REJECTED_BY_USER) ==
+	P2P_SC_FAIL_REJECTED_BY_USER,
+    "P2P status code value mismatch");
+static_assert(
+    static_cast<uint16_t>(
+	ISupplicantP2pIfaceCallback::P2pStatusCode::SUCCESS_DEFERRED) ==
+	P2P_SC_SUCCESS_DEFERRED,
+    "P2P status code value mismatch");
+
+static_assert(
+    static_cast<uint16_t>(
+	ISupplicantP2pIfaceCallback::P2pProvDiscStatusCode::SUCCESS) ==
+	P2P_PROV_DISC_SUCCESS,
+    "P2P status code value mismatch");
+static_assert(
+    static_cast<uint16_t>(
+	ISupplicantP2pIfaceCallback::P2pProvDiscStatusCode::TIMEOUT) ==
+	P2P_PROV_DISC_TIMEOUT,
+    "P2P status code value mismatch");
+static_assert(
+    static_cast<uint16_t>(
+	ISupplicantP2pIfaceCallback::P2pProvDiscStatusCode::REJECTED) ==
+	P2P_PROV_DISC_REJECTED,
+    "P2P status code value mismatch");
+static_assert(
+    static_cast<uint16_t>(
+	ISupplicantP2pIfaceCallback::P2pProvDiscStatusCode::TIMEOUT_JOIN) ==
+	P2P_PROV_DISC_TIMEOUT_JOIN,
+    "P2P status code value mismatch");
+static_assert(
+    static_cast<uint16_t>(
+	ISupplicantP2pIfaceCallback::P2pProvDiscStatusCode::INFO_UNAVAILABLE) ==
+	P2P_PROV_DISC_INFO_UNAVAILABLE,
+    "P2P status code value mismatch");
+}  // namespace implementation
+}  // namespace V1_1
+}  // namespace wifi
+}  // namespace supplicant
+}  // namespace hardware
+}  // namespace android
+#endif  // WPA_SUPPLICANT_HIDL_HIDL_MANAGER_H
diff --git a/wpa_supplicant/hidl/1.1/hidl_return_util.h b/wpa_supplicant/hidl/1.1/hidl_return_util.h
new file mode 100644
index 0000000..dba5f37
--- /dev/null
+++ b/wpa_supplicant/hidl/1.1/hidl_return_util.h
@@ -0,0 +1,101 @@
+/*
+ * 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_RETURN_UTIL_H_
+#define HIDL_RETURN_UTIL_H_
+
+namespace android {
+namespace hardware {
+namespace wifi {
+namespace supplicant {
+namespace V1_1 {
+namespace implementation {
+namespace hidl_return_util {
+
+/**
+ * These utility functions are used to invoke a method on the provided
+ * HIDL interface object.
+ * These functions checks if the provided HIDL interface object is valid.
+ * a) if valid, Invokes the corresponding internal implementation function of
+ * the HIDL method. It then invokes the HIDL continuation callback with
+ * the status and any returned values.
+ * b) if invalid, invokes the HIDL continuation callback with the
+ * provided error status and default values.
+ */
+// Use for HIDL methods which return only an instance of SupplicantStatus.
+template <typename ObjT, typename WorkFuncT, typename... Args>
+Return<void> validateAndCall(
+    ObjT* obj, SupplicantStatusCode status_code_if_invalid, WorkFuncT&& work,
+    const std::function<void(const SupplicantStatus&)>& hidl_cb, Args&&... args)
+{
+	if (obj->isValid()) {
+		hidl_cb((obj->*work)(std::forward<Args>(args)...));
+	} else {
+		hidl_cb({status_code_if_invalid, ""});
+	}
+	return Void();
+}
+
+// Use for HIDL methods which return instance of SupplicantStatus and a single
+// return value.
+template <typename ObjT, typename WorkFuncT, typename ReturnT, typename... Args>
+Return<void> validateAndCall(
+    ObjT* obj, SupplicantStatusCode status_code_if_invalid, WorkFuncT&& work,
+    const std::function<void(const SupplicantStatus&, ReturnT)>& hidl_cb,
+    Args&&... args)
+{
+	if (obj->isValid()) {
+		const auto& ret_pair =
+		    (obj->*work)(std::forward<Args>(args)...);
+		const SupplicantStatus& status = std::get<0>(ret_pair);
+		const auto& ret_value = std::get<1>(ret_pair);
+		hidl_cb(status, ret_value);
+	} else {
+		hidl_cb(
+		    {status_code_if_invalid, ""},
+		    typename std::remove_reference<ReturnT>::type());
+	}
+	return Void();
+}
+
+// Use for HIDL methods which return instance of SupplicantStatus and 2 return
+// values.
+template <
+    typename ObjT, typename WorkFuncT, typename ReturnT1, typename ReturnT2,
+    typename... Args>
+Return<void> validateAndCall(
+    ObjT* obj, SupplicantStatusCode status_code_if_invalid, WorkFuncT&& work,
+    const std::function<void(const SupplicantStatus&, ReturnT1, ReturnT2)>&
+	hidl_cb,
+    Args&&... args)
+{
+	if (obj->isValid()) {
+		const auto& ret_tuple =
+		    (obj->*work)(std::forward<Args>(args)...);
+		const SupplicantStatus& status = std::get<0>(ret_tuple);
+		const auto& ret_value1 = std::get<1>(ret_tuple);
+		const auto& ret_value2 = std::get<2>(ret_tuple);
+		hidl_cb(status, ret_value1, ret_value2);
+	} else {
+		hidl_cb(
+		    {status_code_if_invalid, ""},
+		    typename std::remove_reference<ReturnT1>::type(),
+		    typename std::remove_reference<ReturnT2>::type());
+	}
+	return Void();
+}
+
+}  // namespace hidl_util
+}  // namespace implementation
+}  // namespace V1_1
+}  // namespace supplicant
+}  // namespace wifi
+}  // namespace hardware
+}  // namespace android
+#endif  // HIDL_RETURN_UTIL_H_
diff --git a/wpa_supplicant/hidl/1.1/iface_config_utils.cpp b/wpa_supplicant/hidl/1.1/iface_config_utils.cpp
new file mode 100644
index 0000000..7fe6d19
--- /dev/null
+++ b/wpa_supplicant/hidl/1.1/iface_config_utils.cpp
@@ -0,0 +1,180 @@
+/*
+ * hidl interface for wpa_supplicant daemon
+ * Copyright (struct wpa_supplicant* wpa_s, c) 2004-2016, Jouni Malinen
+ * <j@w1.fi>
+ * Copyright (struct wpa_supplicant* wpa_s, c) 2004-2016, Roshan Pius
+ * <rpius@google.com>
+ *
+ * This software may be distributed under the terms of the BSD license.
+ * See README for more details.
+ */
+
+#include "hidl_manager.h"
+#include "hidl_return_util.h"
+#include "iface_config_utils.h"
+
+namespace {
+constexpr uint32_t kMaxWpsDeviceNameSize = WPS_DEV_NAME_MAX_LEN;
+constexpr uint32_t kMaxWpsManufacturerSize = WPS_MANUFACTURER_MAX_LEN;
+constexpr uint32_t kMaxWpsModelNameSize = WPS_MODEL_NAME_MAX_LEN;
+constexpr uint32_t kMaxWpsModelNumberSize = WPS_MODEL_NUMBER_MAX_LEN;
+constexpr uint32_t kMaxWpsSerialNumberSize = WPS_SERIAL_NUMBER_MAX_LEN;
+
+void processConfigUpdate(struct wpa_supplicant* wpa_s, uint32_t changed_param)
+{
+	wpa_s->conf->changed_parameters |= changed_param;
+	wpa_supplicant_update_config(wpa_s);
+}
+
+// Free any existing pointer stored in |dst| and store the provided string value
+// there.
+int freeAndSetStringConfigParam(
+    struct wpa_supplicant* wpa_s, const std::string& value, uint32_t max_size,
+    uint32_t changed_param, char** dst)
+{
+	if (value.size() > max_size) {
+		return -1;
+	}
+	WPA_ASSERT(dst);
+	os_free(static_cast<void*>(*dst));
+	*dst = os_strdup(value.c_str());
+	processConfigUpdate(wpa_s, changed_param);
+	return 0;
+}
+
+std::string convertWpsConfigMethodsMaskToString(uint16_t config_methods)
+{
+	using WpsConfigMethods =
+	    android::hardware::wifi::supplicant::V1_0::WpsConfigMethods;
+	std::string config_methods_str;
+	for (const auto& flag_and_name :
+	     {std::make_pair(WpsConfigMethods::USBA, "usba"),
+	      {WpsConfigMethods::ETHERNET, "ethernet"},
+	      {WpsConfigMethods::LABEL, "label"},
+	      {WpsConfigMethods::DISPLAY, "display"},
+	      {WpsConfigMethods::INT_NFC_TOKEN, "int_nfc_token"},
+	      {WpsConfigMethods::EXT_NFC_TOKEN, "ext_nfc_token"},
+	      {WpsConfigMethods::NFC_INTERFACE, "nfc_interface"},
+	      {WpsConfigMethods::PUSHBUTTON, "push_button"},
+	      {WpsConfigMethods::KEYPAD, "keypad"},
+	      {WpsConfigMethods::VIRT_PUSHBUTTON, "virtual_push_button"},
+	      {WpsConfigMethods::PHY_PUSHBUTTON, "physical_push_button"},
+	      {WpsConfigMethods::P2PS, "p2ps"},
+	      {WpsConfigMethods::VIRT_DISPLAY, "virtual_display"},
+	      {WpsConfigMethods::PHY_DISPLAY, "physical_display"}}) {
+		const auto flag =
+		    static_cast<std::underlying_type<WpsConfigMethods>::type>(
+			flag_and_name.first);
+		if ((config_methods & flag) == flag) {
+			config_methods_str += flag_and_name.second;
+			config_methods_str += " ";
+		}
+	}
+	return config_methods_str;
+}
+}  // namespace
+
+namespace android {
+namespace hardware {
+namespace wifi {
+namespace supplicant {
+namespace V1_1 {
+namespace implementation {
+namespace iface_config_utils {
+SupplicantStatus setWpsDeviceName(
+    struct wpa_supplicant* wpa_s, const std::string& name)
+{
+	WPA_ASSERT(wpa_s);
+	if (freeAndSetStringConfigParam(
+		wpa_s, name, kMaxWpsDeviceNameSize, CFG_CHANGED_DEVICE_NAME,
+		&wpa_s->conf->device_name)) {
+		return {SupplicantStatusCode::FAILURE_ARGS_INVALID, ""};
+	}
+	return {SupplicantStatusCode::SUCCESS, ""};
+}
+
+SupplicantStatus setWpsDeviceType(
+    struct wpa_supplicant* wpa_s, const std::array<uint8_t, 8>& type)
+{
+	WPA_ASSERT(wpa_s);
+	WPA_ASSERT(type.size() == WPS_DEV_TYPE_LEN);
+	os_memcpy(wpa_s->conf->device_type, type.data(), WPS_DEV_TYPE_LEN);
+	processConfigUpdate(wpa_s, CFG_CHANGED_DEVICE_TYPE);
+	return {SupplicantStatusCode::SUCCESS, ""};
+}
+
+SupplicantStatus setWpsManufacturer(
+    struct wpa_supplicant* wpa_s, const std::string& manufacturer)
+{
+	WPA_ASSERT(wpa_s);
+	if (freeAndSetStringConfigParam(
+		wpa_s, manufacturer, kMaxWpsManufacturerSize,
+		CFG_CHANGED_WPS_STRING, &wpa_s->conf->manufacturer)) {
+		return {SupplicantStatusCode::FAILURE_ARGS_INVALID, ""};
+	}
+	return {SupplicantStatusCode::SUCCESS, ""};
+}
+
+SupplicantStatus setWpsModelName(
+    struct wpa_supplicant* wpa_s, const std::string& model_name)
+{
+	WPA_ASSERT(wpa_s);
+	if (freeAndSetStringConfigParam(
+		wpa_s, model_name, kMaxWpsModelNameSize, CFG_CHANGED_WPS_STRING,
+		&wpa_s->conf->model_name)) {
+		return {SupplicantStatusCode::FAILURE_ARGS_INVALID, ""};
+	}
+	return {SupplicantStatusCode::SUCCESS, ""};
+}
+
+SupplicantStatus setWpsModelNumber(
+    struct wpa_supplicant* wpa_s, const std::string& model_number)
+{
+	WPA_ASSERT(wpa_s);
+	if (freeAndSetStringConfigParam(
+		wpa_s, model_number, kMaxWpsModelNumberSize,
+		CFG_CHANGED_WPS_STRING, &wpa_s->conf->model_number)) {
+		return {SupplicantStatusCode::FAILURE_ARGS_INVALID, ""};
+	}
+	return {SupplicantStatusCode::SUCCESS, ""};
+}
+
+SupplicantStatus setWpsSerialNumber(
+    struct wpa_supplicant* wpa_s, const std::string& serial_number)
+{
+	WPA_ASSERT(wpa_s);
+	if (freeAndSetStringConfigParam(
+		wpa_s, serial_number, kMaxWpsSerialNumberSize,
+		CFG_CHANGED_WPS_STRING, &wpa_s->conf->serial_number)) {
+		return {SupplicantStatusCode::FAILURE_ARGS_INVALID, ""};
+	}
+	return {SupplicantStatusCode::SUCCESS, ""};
+}
+
+SupplicantStatus setWpsConfigMethods(
+    struct wpa_supplicant* wpa_s, uint16_t config_methods)
+{
+	WPA_ASSERT(wpa_s);
+	if (freeAndSetStringConfigParam(
+		wpa_s, convertWpsConfigMethodsMaskToString(config_methods),
+		UINT32_MAX, CFG_CHANGED_CONFIG_METHODS,
+		&wpa_s->conf->config_methods)) {
+		return {SupplicantStatusCode::FAILURE_ARGS_INVALID, ""};
+	}
+	return {SupplicantStatusCode::SUCCESS, ""};
+}
+
+SupplicantStatus setExternalSim(
+    struct wpa_supplicant* wpa_s, bool useExternalSim)
+{
+	WPA_ASSERT(wpa_s);
+	wpa_s->conf->external_sim = useExternalSim ? 1 : 0;
+	return {SupplicantStatusCode::SUCCESS, ""};
+}
+}  // namespace iface_config_utils
+}  // namespace implementation
+}  // namespace V1_1
+}  // namespace wifi
+}  // namespace supplicant
+}  // namespace hardware
+}  // namespace android
diff --git a/wpa_supplicant/hidl/1.1/iface_config_utils.h b/wpa_supplicant/hidl/1.1/iface_config_utils.h
new file mode 100644
index 0000000..39f5548
--- /dev/null
+++ b/wpa_supplicant/hidl/1.1/iface_config_utils.h
@@ -0,0 +1,59 @@
+/*
+ * hidl interface for wpa_supplicant daemon
+ * Copyright (struct wpa_supplicant* wpa_s, c) 2004-2016, Jouni Malinen
+ * <j@w1.fi>
+ * Copyright (struct wpa_supplicant* wpa_s, 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_CONFIG_UTILS_H
+#define WPA_SUPPLICANT_HIDL_IFACE_CONFIG_UTILS_H
+
+#include <android-base/macros.h>
+
+extern "C" {
+#include "utils/common.h"
+#include "utils/includes.h"
+#include "wpa_supplicant_i.h"
+#include "config.h"
+}
+
+/**
+ * Utility functions to set various config parameters of an iface via HIDL
+ * methods.
+ */
+namespace android {
+namespace hardware {
+namespace wifi {
+namespace supplicant {
+namespace V1_1 {
+namespace implementation {
+namespace iface_config_utils {
+SupplicantStatus setWpsDeviceName(
+    struct wpa_supplicant* wpa_s, const std::string& name);
+SupplicantStatus setWpsDeviceType(
+    struct wpa_supplicant* wpa_s, const std::array<uint8_t, 8>& type);
+SupplicantStatus setWpsManufacturer(
+    struct wpa_supplicant* wpa_s, const std::string& manufacturer);
+SupplicantStatus setWpsModelName(
+    struct wpa_supplicant* wpa_s, const std::string& model_name);
+SupplicantStatus setWpsModelNumber(
+    struct wpa_supplicant* wpa_s, const std::string& model_number);
+SupplicantStatus setWpsSerialNumber(
+    struct wpa_supplicant* wpa_s, const std::string& serial_number);
+SupplicantStatus setWpsConfigMethods(
+    struct wpa_supplicant* wpa_s, uint16_t config_methods);
+SupplicantStatus setExternalSim(
+    struct wpa_supplicant* wpa_s, bool useExternalSim);
+}  // namespace iface_config_utils
+}  // namespace implementation
+}  // namespace V1_1
+}  // namespace wifi
+}  // namespace supplicant
+}  // namespace hardware
+}  // namespace android
+
+#endif  // WPA_SUPPLICANT_HIDL_IFACE_CONFIG_UTILS_H
diff --git a/wpa_supplicant/hidl/1.1/misc_utils.h b/wpa_supplicant/hidl/1.1/misc_utils.h
new file mode 100644
index 0000000..8b2ae3f
--- /dev/null
+++ b/wpa_supplicant/hidl/1.1/misc_utils.h
@@ -0,0 +1,72 @@
+/*
+ * 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 MISC_UTILS_H_
+#define MISC_UTILS_H_
+
+extern "C" {
+#include "wpabuf.h"
+}
+
+namespace {
+constexpr size_t kWpsPinNumDigits = 8;
+// Custom deleter for wpabuf.
+void freeWpaBuf(wpabuf *ptr) { wpabuf_free(ptr); }
+}  // namespace
+
+namespace android {
+namespace hardware {
+namespace wifi {
+namespace supplicant {
+namespace V1_1 {
+namespace implementation {
+namespace misc_utils {
+using wpabuf_unique_ptr = std::unique_ptr<wpabuf, void (*)(wpabuf *)>;
+
+// Creates a unique_ptr for wpabuf ptr with a custom deleter.
+inline wpabuf_unique_ptr createWpaBufUniquePtr(struct wpabuf *raw_ptr)
+{
+	return {raw_ptr, freeWpaBuf};
+}
+
+// Creates a wpabuf ptr with a custom deleter copying the data from the provided
+// vector.
+inline wpabuf_unique_ptr convertVectorToWpaBuf(const std::vector<uint8_t> &data)
+{
+	return createWpaBufUniquePtr(
+	    wpabuf_alloc_copy(data.data(), data.size()));
+}
+
+// Copies the provided wpabuf contents to a std::vector.
+inline std::vector<uint8_t> convertWpaBufToVector(const struct wpabuf *buf)
+{
+	if (buf) {
+		return std::vector<uint8_t>(
+		    wpabuf_head_u8(buf), wpabuf_head_u8(buf) + wpabuf_len(buf));
+	} else {
+		return std::vector<uint8_t>();
+	}
+}
+
+// Returns a string holding the wps pin.
+inline std::string convertWpsPinToString(int pin)
+{
+	char pin_str[kWpsPinNumDigits + 1];
+	snprintf(pin_str, sizeof(pin_str), "%08d", pin);
+	return pin_str;
+}
+
+}  // namespace misc_utils
+}  // namespace implementation
+}  // namespace V1_1
+}  // namespace supplicant
+}  // namespace wifi
+}  // namespace hardware
+}  // namespace android
+#endif  // MISC_UTILS_H_
diff --git a/wpa_supplicant/hidl/1.1/p2p_iface.cpp b/wpa_supplicant/hidl/1.1/p2p_iface.cpp
new file mode 100644
index 0000000..5de383d
--- /dev/null
+++ b/wpa_supplicant/hidl/1.1/p2p_iface.cpp
@@ -0,0 +1,1284 @@
+/*
+ * hidl interface for wpa_supplicant daemon
+ * Copyright (c) 2004-2016, Jouni Malinen <j@w1.fi>
+ * Copyright (c) 2004-2016, Roshan Pius <rpius@google.com>
+ * Copyright (C) 2017 Sony Mobile Communications Inc.
+ *
+ * This software may be distributed under the terms of the BSD license.
+ * See README for more details.
+ */
+
+#include "hidl_manager.h"
+#include "hidl_return_util.h"
+#include "iface_config_utils.h"
+#include "misc_utils.h"
+#include "p2p_iface.h"
+
+extern "C" {
+#include "ap.h"
+#include "wps_supplicant.h"
+#include "wifi_display.h"
+}
+
+namespace {
+const char kConfigMethodStrPbc[] = "pbc";
+const char kConfigMethodStrDisplay[] = "display";
+const char kConfigMethodStrKeypad[] = "keypad";
+constexpr char kSetMiracastMode[] = "MIRACAST ";
+constexpr uint8_t kWfdDeviceInfoSubelemId = 0;
+constexpr char kWfdDeviceInfoSubelemLenHexStr[] = "0006";
+
+using android::hardware::wifi::supplicant::V1_0::ISupplicantP2pIface;
+uint8_t convertHidlMiracastModeToInternal(
+    ISupplicantP2pIface::MiracastMode mode)
+{
+	switch (mode) {
+	case ISupplicantP2pIface::MiracastMode::DISABLED:
+		return 0;
+	case ISupplicantP2pIface::MiracastMode::SOURCE:
+		return 1;
+	case ISupplicantP2pIface::MiracastMode::SINK:
+		return 2;
+	};
+	WPA_ASSERT(false);
+}
+}  // namespace
+
+namespace android {
+namespace hardware {
+namespace wifi {
+namespace supplicant {
+namespace V1_1 {
+namespace implementation {
+using hidl_return_util::validateAndCall;
+
+P2pIface::P2pIface(struct wpa_global* wpa_global, const char ifname[])
+    : wpa_global_(wpa_global), ifname_(ifname), is_valid_(true)
+{
+}
+
+void P2pIface::invalidate() { is_valid_ = false; }
+bool P2pIface::isValid()
+{
+	return (is_valid_ && (retrieveIfacePtr() != nullptr));
+}
+Return<void> P2pIface::getName(getName_cb _hidl_cb)
+{
+	return validateAndCall(
+	    this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
+	    &P2pIface::getNameInternal, _hidl_cb);
+}
+
+Return<void> P2pIface::getType(getType_cb _hidl_cb)
+{
+	return validateAndCall(
+	    this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
+	    &P2pIface::getTypeInternal, _hidl_cb);
+}
+
+Return<void> P2pIface::addNetwork(addNetwork_cb _hidl_cb)
+{
+	return validateAndCall(
+	    this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
+	    &P2pIface::addNetworkInternal, _hidl_cb);
+}
+
+Return<void> P2pIface::removeNetwork(
+    SupplicantNetworkId id, removeNetwork_cb _hidl_cb)
+{
+	return validateAndCall(
+	    this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
+	    &P2pIface::removeNetworkInternal, _hidl_cb, id);
+}
+
+Return<void> P2pIface::getNetwork(
+    SupplicantNetworkId id, getNetwork_cb _hidl_cb)
+{
+	return validateAndCall(
+	    this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
+	    &P2pIface::getNetworkInternal, _hidl_cb, id);
+}
+
+Return<void> P2pIface::listNetworks(listNetworks_cb _hidl_cb)
+{
+	return validateAndCall(
+	    this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
+	    &P2pIface::listNetworksInternal, _hidl_cb);
+}
+
+Return<void> P2pIface::registerCallback(
+    const sp<ISupplicantP2pIfaceCallback>& callback,
+    registerCallback_cb _hidl_cb)
+{
+	return validateAndCall(
+	    this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
+	    &P2pIface::registerCallbackInternal, _hidl_cb, callback);
+}
+
+Return<void> P2pIface::getDeviceAddress(getDeviceAddress_cb _hidl_cb)
+{
+	return validateAndCall(
+	    this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
+	    &P2pIface::getDeviceAddressInternal, _hidl_cb);
+}
+
+Return<void> P2pIface::setSsidPostfix(
+    const hidl_vec<uint8_t>& postfix, setSsidPostfix_cb _hidl_cb)
+{
+	return validateAndCall(
+	    this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
+	    &P2pIface::setSsidPostfixInternal, _hidl_cb, postfix);
+}
+
+Return<void> P2pIface::setGroupIdle(
+    const hidl_string& group_ifname, uint32_t timeout_in_sec,
+    setGroupIdle_cb _hidl_cb)
+{
+	return validateAndCall(
+	    this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
+	    &P2pIface::setGroupIdleInternal, _hidl_cb, group_ifname,
+	    timeout_in_sec);
+}
+
+Return<void> P2pIface::setPowerSave(
+    const hidl_string& group_ifname, bool enable, setPowerSave_cb _hidl_cb)
+{
+	return validateAndCall(
+	    this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
+	    &P2pIface::setPowerSaveInternal, _hidl_cb, group_ifname, enable);
+}
+
+Return<void> P2pIface::find(uint32_t timeout_in_sec, find_cb _hidl_cb)
+{
+	return validateAndCall(
+	    this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
+	    &P2pIface::findInternal, _hidl_cb, timeout_in_sec);
+}
+
+Return<void> P2pIface::stopFind(stopFind_cb _hidl_cb)
+{
+	return validateAndCall(
+	    this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
+	    &P2pIface::stopFindInternal, _hidl_cb);
+}
+
+Return<void> P2pIface::flush(flush_cb _hidl_cb)
+{
+	return validateAndCall(
+	    this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
+	    &P2pIface::flushInternal, _hidl_cb);
+}
+
+Return<void> P2pIface::connect(
+    const hidl_array<uint8_t, 6>& peer_address,
+    ISupplicantP2pIface::WpsProvisionMethod provision_method,
+    const hidl_string& pre_selected_pin, bool join_existing_group,
+    bool persistent, uint32_t go_intent, connect_cb _hidl_cb)
+{
+	return validateAndCall(
+	    this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
+	    &P2pIface::connectInternal, _hidl_cb, peer_address,
+	    provision_method, pre_selected_pin, join_existing_group, persistent,
+	    go_intent);
+}
+
+Return<void> P2pIface::cancelConnect(cancelConnect_cb _hidl_cb)
+{
+	return validateAndCall(
+	    this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
+	    &P2pIface::cancelConnectInternal, _hidl_cb);
+}
+
+Return<void> P2pIface::provisionDiscovery(
+    const hidl_array<uint8_t, 6>& peer_address,
+    ISupplicantP2pIface::WpsProvisionMethod provision_method,
+    provisionDiscovery_cb _hidl_cb)
+{
+	return validateAndCall(
+	    this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
+	    &P2pIface::provisionDiscoveryInternal, _hidl_cb, peer_address,
+	    provision_method);
+}
+
+Return<void> P2pIface::addGroup(
+    bool persistent, SupplicantNetworkId persistent_network_id,
+    addGroup_cb _hidl_cb)
+{
+	return validateAndCall(
+	    this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
+	    &P2pIface::addGroupInternal, _hidl_cb, persistent,
+	    persistent_network_id);
+}
+
+Return<void> P2pIface::removeGroup(
+    const hidl_string& group_ifname, removeGroup_cb _hidl_cb)
+{
+	return validateAndCall(
+	    this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
+	    &P2pIface::removeGroupInternal, _hidl_cb, group_ifname);
+}
+
+Return<void> P2pIface::reject(
+    const hidl_array<uint8_t, 6>& peer_address, reject_cb _hidl_cb)
+{
+	return validateAndCall(
+	    this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
+	    &P2pIface::rejectInternal, _hidl_cb, peer_address);
+}
+
+Return<void> P2pIface::invite(
+    const hidl_string& group_ifname,
+    const hidl_array<uint8_t, 6>& go_device_address,
+    const hidl_array<uint8_t, 6>& peer_address, invite_cb _hidl_cb)
+{
+	return validateAndCall(
+	    this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
+	    &P2pIface::inviteInternal, _hidl_cb, group_ifname,
+	    go_device_address, peer_address);
+}
+
+Return<void> P2pIface::reinvoke(
+    SupplicantNetworkId persistent_network_id,
+    const hidl_array<uint8_t, 6>& peer_address, reinvoke_cb _hidl_cb)
+{
+	return validateAndCall(
+	    this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
+	    &P2pIface::reinvokeInternal, _hidl_cb, persistent_network_id,
+	    peer_address);
+}
+
+Return<void> P2pIface::configureExtListen(
+    uint32_t period_in_millis, uint32_t interval_in_millis,
+    configureExtListen_cb _hidl_cb)
+{
+	return validateAndCall(
+	    this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
+	    &P2pIface::configureExtListenInternal, _hidl_cb, period_in_millis,
+	    interval_in_millis);
+}
+
+Return<void> P2pIface::setListenChannel(
+    uint32_t channel, uint32_t operating_class, setListenChannel_cb _hidl_cb)
+{
+	return validateAndCall(
+	    this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
+	    &P2pIface::setListenChannelInternal, _hidl_cb, channel,
+	    operating_class);
+}
+
+Return<void> P2pIface::setDisallowedFrequencies(
+    const hidl_vec<FreqRange>& ranges, setDisallowedFrequencies_cb _hidl_cb)
+{
+	return validateAndCall(
+	    this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
+	    &P2pIface::setDisallowedFrequenciesInternal, _hidl_cb, ranges);
+}
+
+Return<void> P2pIface::getSsid(
+    const hidl_array<uint8_t, 6>& peer_address, getSsid_cb _hidl_cb)
+{
+	return validateAndCall(
+	    this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
+	    &P2pIface::getSsidInternal, _hidl_cb, peer_address);
+}
+
+Return<void> P2pIface::getGroupCapability(
+    const hidl_array<uint8_t, 6>& peer_address, getGroupCapability_cb _hidl_cb)
+{
+	return validateAndCall(
+	    this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
+	    &P2pIface::getGroupCapabilityInternal, _hidl_cb, peer_address);
+}
+
+Return<void> P2pIface::addBonjourService(
+    const hidl_vec<uint8_t>& query, const hidl_vec<uint8_t>& response,
+    addBonjourService_cb _hidl_cb)
+{
+	return validateAndCall(
+	    this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
+	    &P2pIface::addBonjourServiceInternal, _hidl_cb, query, response);
+}
+
+Return<void> P2pIface::removeBonjourService(
+    const hidl_vec<uint8_t>& query, removeBonjourService_cb _hidl_cb)
+{
+	return validateAndCall(
+	    this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
+	    &P2pIface::removeBonjourServiceInternal, _hidl_cb, query);
+}
+
+Return<void> P2pIface::addUpnpService(
+    uint32_t version, const hidl_string& service_name,
+    addUpnpService_cb _hidl_cb)
+{
+	return validateAndCall(
+	    this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
+	    &P2pIface::addUpnpServiceInternal, _hidl_cb, version, service_name);
+}
+
+Return<void> P2pIface::removeUpnpService(
+    uint32_t version, const hidl_string& service_name,
+    removeUpnpService_cb _hidl_cb)
+{
+	return validateAndCall(
+	    this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
+	    &P2pIface::removeUpnpServiceInternal, _hidl_cb, version,
+	    service_name);
+}
+
+Return<void> P2pIface::flushServices(flushServices_cb _hidl_cb)
+{
+	return validateAndCall(
+	    this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
+	    &P2pIface::flushServicesInternal, _hidl_cb);
+}
+
+Return<void> P2pIface::requestServiceDiscovery(
+    const hidl_array<uint8_t, 6>& peer_address, const hidl_vec<uint8_t>& query,
+    requestServiceDiscovery_cb _hidl_cb)
+{
+	return validateAndCall(
+	    this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
+	    &P2pIface::requestServiceDiscoveryInternal, _hidl_cb, peer_address,
+	    query);
+}
+
+Return<void> P2pIface::cancelServiceDiscovery(
+    uint64_t identifier, cancelServiceDiscovery_cb _hidl_cb)
+{
+	return validateAndCall(
+	    this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
+	    &P2pIface::cancelServiceDiscoveryInternal, _hidl_cb, identifier);
+}
+
+Return<void> P2pIface::setMiracastMode(
+    ISupplicantP2pIface::MiracastMode mode, setMiracastMode_cb _hidl_cb)
+{
+	return validateAndCall(
+	    this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
+	    &P2pIface::setMiracastModeInternal, _hidl_cb, mode);
+}
+
+Return<void> P2pIface::startWpsPbc(
+    const hidl_string& group_ifname, const hidl_array<uint8_t, 6>& bssid,
+    startWpsPbc_cb _hidl_cb)
+{
+	return validateAndCall(
+	    this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
+	    &P2pIface::startWpsPbcInternal, _hidl_cb, group_ifname, bssid);
+}
+
+Return<void> P2pIface::startWpsPinKeypad(
+    const hidl_string& group_ifname, const hidl_string& pin,
+    startWpsPinKeypad_cb _hidl_cb)
+{
+	return validateAndCall(
+	    this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
+	    &P2pIface::startWpsPinKeypadInternal, _hidl_cb, group_ifname, pin);
+}
+
+Return<void> P2pIface::startWpsPinDisplay(
+    const hidl_string& group_ifname, const hidl_array<uint8_t, 6>& bssid,
+    startWpsPinDisplay_cb _hidl_cb)
+{
+	return validateAndCall(
+	    this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
+	    &P2pIface::startWpsPinDisplayInternal, _hidl_cb, group_ifname,
+	    bssid);
+}
+
+Return<void> P2pIface::cancelWps(
+    const hidl_string& group_ifname, cancelWps_cb _hidl_cb)
+{
+	return validateAndCall(
+	    this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
+	    &P2pIface::cancelWpsInternal, _hidl_cb, group_ifname);
+}
+
+Return<void> P2pIface::setWpsDeviceName(
+    const hidl_string& name, setWpsDeviceName_cb _hidl_cb)
+{
+	return validateAndCall(
+	    this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
+	    &P2pIface::setWpsDeviceNameInternal, _hidl_cb, name);
+}
+
+Return<void> P2pIface::setWpsDeviceType(
+    const hidl_array<uint8_t, 8>& type, setWpsDeviceType_cb _hidl_cb)
+{
+	return validateAndCall(
+	    this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
+	    &P2pIface::setWpsDeviceTypeInternal, _hidl_cb, type);
+}
+
+Return<void> P2pIface::setWpsManufacturer(
+    const hidl_string& manufacturer, setWpsManufacturer_cb _hidl_cb)
+{
+	return validateAndCall(
+	    this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
+	    &P2pIface::setWpsManufacturerInternal, _hidl_cb, manufacturer);
+}
+
+Return<void> P2pIface::setWpsModelName(
+    const hidl_string& model_name, setWpsModelName_cb _hidl_cb)
+{
+	return validateAndCall(
+	    this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
+	    &P2pIface::setWpsModelNameInternal, _hidl_cb, model_name);
+}
+
+Return<void> P2pIface::setWpsModelNumber(
+    const hidl_string& model_number, setWpsModelNumber_cb _hidl_cb)
+{
+	return validateAndCall(
+	    this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
+	    &P2pIface::setWpsModelNumberInternal, _hidl_cb, model_number);
+}
+
+Return<void> P2pIface::setWpsSerialNumber(
+    const hidl_string& serial_number, setWpsSerialNumber_cb _hidl_cb)
+{
+	return validateAndCall(
+	    this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
+	    &P2pIface::setWpsSerialNumberInternal, _hidl_cb, serial_number);
+}
+
+Return<void> P2pIface::setWpsConfigMethods(
+    uint16_t config_methods, setWpsConfigMethods_cb _hidl_cb)
+{
+	return validateAndCall(
+	    this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
+	    &P2pIface::setWpsConfigMethodsInternal, _hidl_cb, config_methods);
+}
+
+Return<void> P2pIface::enableWfd(bool enable, enableWfd_cb _hidl_cb)
+{
+	return validateAndCall(
+	    this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
+	    &P2pIface::enableWfdInternal, _hidl_cb, enable);
+}
+
+Return<void> P2pIface::setWfdDeviceInfo(
+    const hidl_array<uint8_t, 6>& info, setWfdDeviceInfo_cb _hidl_cb)
+{
+	return validateAndCall(
+	    this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
+	    &P2pIface::setWfdDeviceInfoInternal, _hidl_cb, info);
+}
+
+Return<void> P2pIface::createNfcHandoverRequestMessage(
+    createNfcHandoverRequestMessage_cb _hidl_cb)
+{
+	return validateAndCall(
+	    this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
+	    &P2pIface::createNfcHandoverRequestMessageInternal, _hidl_cb);
+}
+
+Return<void> P2pIface::createNfcHandoverSelectMessage(
+    createNfcHandoverSelectMessage_cb _hidl_cb)
+{
+	return validateAndCall(
+	    this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
+	    &P2pIface::createNfcHandoverSelectMessageInternal, _hidl_cb);
+}
+
+Return<void> P2pIface::reportNfcHandoverResponse(
+    const hidl_vec<uint8_t>& request, reportNfcHandoverResponse_cb _hidl_cb)
+{
+	return validateAndCall(
+	    this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
+	    &P2pIface::reportNfcHandoverResponseInternal, _hidl_cb, request);
+}
+
+Return<void> P2pIface::reportNfcHandoverInitiation(
+    const hidl_vec<uint8_t>& select, reportNfcHandoverInitiation_cb _hidl_cb)
+{
+	return validateAndCall(
+	    this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
+	    &P2pIface::reportNfcHandoverInitiationInternal, _hidl_cb, select);
+}
+
+Return<void> P2pIface::saveConfig(saveConfig_cb _hidl_cb)
+{
+	return validateAndCall(
+	    this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
+	    &P2pIface::saveConfigInternal, _hidl_cb);
+}
+
+std::pair<SupplicantStatus, std::string> P2pIface::getNameInternal()
+{
+	return {{SupplicantStatusCode::SUCCESS, ""}, ifname_};
+}
+
+std::pair<SupplicantStatus, IfaceType> P2pIface::getTypeInternal()
+{
+	return {{SupplicantStatusCode::SUCCESS, ""}, IfaceType::P2P};
+}
+
+std::pair<SupplicantStatus, sp<ISupplicantP2pNetwork>>
+P2pIface::addNetworkInternal()
+{
+	android::sp<ISupplicantP2pNetwork> network;
+	struct wpa_supplicant* wpa_s = retrieveIfacePtr();
+	struct wpa_ssid* ssid = wpa_supplicant_add_network(wpa_s);
+	if (!ssid) {
+		return {{SupplicantStatusCode::FAILURE_UNKNOWN, ""}, network};
+	}
+	HidlManager* hidl_manager = HidlManager::getInstance();
+	if (!hidl_manager ||
+	    hidl_manager->getP2pNetworkHidlObjectByIfnameAndNetworkId(
+		wpa_s->ifname, ssid->id, &network)) {
+		return {{SupplicantStatusCode::FAILURE_UNKNOWN, ""}, network};
+	}
+	return {{SupplicantStatusCode::SUCCESS, ""}, network};
+}
+
+SupplicantStatus P2pIface::removeNetworkInternal(SupplicantNetworkId id)
+{
+	struct wpa_supplicant* wpa_s = retrieveIfacePtr();
+	int result = wpa_supplicant_remove_network(wpa_s, id);
+	if (result == -1) {
+		return {SupplicantStatusCode::FAILURE_NETWORK_UNKNOWN, ""};
+	}
+	if (result != 0) {
+		return {SupplicantStatusCode::FAILURE_UNKNOWN, ""};
+	}
+	return {SupplicantStatusCode::SUCCESS, ""};
+}
+
+std::pair<SupplicantStatus, sp<ISupplicantP2pNetwork>>
+P2pIface::getNetworkInternal(SupplicantNetworkId id)
+{
+	android::sp<ISupplicantP2pNetwork> network;
+	struct wpa_supplicant* wpa_s = retrieveIfacePtr();
+	struct wpa_ssid* ssid = wpa_config_get_network(wpa_s->conf, id);
+	if (!ssid) {
+		return {{SupplicantStatusCode::FAILURE_NETWORK_UNKNOWN, ""},
+			network};
+	}
+	HidlManager* hidl_manager = HidlManager::getInstance();
+	if (!hidl_manager ||
+	    hidl_manager->getP2pNetworkHidlObjectByIfnameAndNetworkId(
+		wpa_s->ifname, ssid->id, &network)) {
+		return {{SupplicantStatusCode::FAILURE_UNKNOWN, ""}, network};
+	}
+	return {{SupplicantStatusCode::SUCCESS, ""}, network};
+}
+
+std::pair<SupplicantStatus, std::vector<SupplicantNetworkId>>
+P2pIface::listNetworksInternal()
+{
+	std::vector<SupplicantNetworkId> network_ids;
+	struct wpa_supplicant* wpa_s = retrieveIfacePtr();
+	for (struct wpa_ssid* wpa_ssid = wpa_s->conf->ssid; wpa_ssid;
+	     wpa_ssid = wpa_ssid->next) {
+		network_ids.emplace_back(wpa_ssid->id);
+	}
+	return {{SupplicantStatusCode::SUCCESS, ""}, std::move(network_ids)};
+}
+
+SupplicantStatus P2pIface::registerCallbackInternal(
+    const sp<ISupplicantP2pIfaceCallback>& callback)
+{
+	HidlManager* hidl_manager = HidlManager::getInstance();
+	if (!hidl_manager ||
+	    hidl_manager->addP2pIfaceCallbackHidlObject(ifname_, callback)) {
+		return {SupplicantStatusCode::FAILURE_UNKNOWN, ""};
+	}
+	return {SupplicantStatusCode::SUCCESS, ""};
+}
+
+std::pair<SupplicantStatus, std::array<uint8_t, 6>>
+P2pIface::getDeviceAddressInternal()
+{
+	struct wpa_supplicant* wpa_s = retrieveIfacePtr();
+	std::array<uint8_t, 6> addr;
+	static_assert(ETH_ALEN == addr.size(), "Size mismatch");
+	os_memcpy(addr.data(), wpa_s->global->p2p_dev_addr, ETH_ALEN);
+	return {{SupplicantStatusCode::SUCCESS, ""}, addr};
+}
+
+SupplicantStatus P2pIface::setSsidPostfixInternal(
+    const std::vector<uint8_t>& postfix)
+{
+	struct wpa_supplicant* wpa_s = retrieveIfacePtr();
+	if (p2p_set_ssid_postfix(
+		wpa_s->global->p2p, postfix.data(), postfix.size())) {
+		return {SupplicantStatusCode::FAILURE_UNKNOWN, ""};
+	}
+	return {SupplicantStatusCode::SUCCESS, ""};
+}
+
+SupplicantStatus P2pIface::setGroupIdleInternal(
+    const std::string& group_ifname, uint32_t timeout_in_sec)
+{
+	struct wpa_supplicant* wpa_group_s =
+	    retrieveGroupIfacePtr(group_ifname);
+	if (!wpa_group_s) {
+		return {SupplicantStatusCode::FAILURE_IFACE_UNKNOWN, ""};
+	}
+	wpa_group_s->conf->p2p_group_idle = timeout_in_sec;
+	return {SupplicantStatusCode::SUCCESS, ""};
+}
+
+SupplicantStatus P2pIface::setPowerSaveInternal(
+    const std::string& group_ifname, bool enable)
+{
+	struct wpa_supplicant* wpa_group_s =
+	    retrieveGroupIfacePtr(group_ifname);
+	if (!wpa_group_s) {
+		return {SupplicantStatusCode::FAILURE_IFACE_UNKNOWN, ""};
+	}
+	if (wpa_drv_set_p2p_powersave(wpa_group_s, enable, -1, -1)) {
+		return {SupplicantStatusCode::FAILURE_UNKNOWN, ""};
+	}
+	return {SupplicantStatusCode::SUCCESS, ""};
+}
+
+SupplicantStatus P2pIface::findInternal(uint32_t timeout_in_sec)
+{
+	struct wpa_supplicant* wpa_s = retrieveIfacePtr();
+	if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED) {
+		return {SupplicantStatusCode::FAILURE_IFACE_DISABLED, ""};
+	}
+	uint32_t search_delay = wpas_p2p_search_delay(wpa_s);
+	if (wpas_p2p_find(
+		wpa_s, timeout_in_sec, P2P_FIND_START_WITH_FULL, 0, nullptr,
+		nullptr, search_delay, 0, nullptr, 0)) {
+		return {SupplicantStatusCode::FAILURE_UNKNOWN, ""};
+	}
+	return {SupplicantStatusCode::SUCCESS, ""};
+}
+
+SupplicantStatus P2pIface::stopFindInternal()
+{
+	struct wpa_supplicant* wpa_s = retrieveIfacePtr();
+	if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED) {
+		return {SupplicantStatusCode::FAILURE_IFACE_DISABLED, ""};
+	}
+	wpas_p2p_stop_find(wpa_s);
+	return {SupplicantStatusCode::SUCCESS, ""};
+}
+
+SupplicantStatus P2pIface::flushInternal()
+{
+	struct wpa_supplicant* wpa_s = retrieveIfacePtr();
+	os_memset(wpa_s->p2p_auth_invite, 0, ETH_ALEN);
+	wpa_s->force_long_sd = 0;
+	wpas_p2p_stop_find(wpa_s);
+	wpa_s->parent->p2ps_method_config_any = 0;
+	if (wpa_s->global->p2p)
+		p2p_flush(wpa_s->global->p2p);
+	return {SupplicantStatusCode::SUCCESS, ""};
+}
+
+// This method only implements support for subset (needed by Android framework)
+// of parameters that can be specified for connect.
+std::pair<SupplicantStatus, std::string> P2pIface::connectInternal(
+    const std::array<uint8_t, 6>& peer_address,
+    ISupplicantP2pIface::WpsProvisionMethod provision_method,
+    const std::string& pre_selected_pin, bool join_existing_group,
+    bool persistent, uint32_t go_intent)
+{
+	struct wpa_supplicant* wpa_s = retrieveIfacePtr();
+	if (go_intent > 15) {
+		return {{SupplicantStatusCode::FAILURE_ARGS_INVALID, ""}, {}};
+	}
+	int go_intent_signed = join_existing_group ? -1 : go_intent;
+	p2p_wps_method wps_method = {};
+	switch (provision_method) {
+	case WpsProvisionMethod::PBC:
+		wps_method = WPS_PBC;
+		break;
+	case WpsProvisionMethod::DISPLAY:
+		wps_method = WPS_PIN_DISPLAY;
+		break;
+	case WpsProvisionMethod::KEYPAD:
+		wps_method = WPS_PIN_KEYPAD;
+		break;
+	}
+	int vht = wpa_s->conf->p2p_go_vht;
+	int ht40 = wpa_s->conf->p2p_go_ht40 || vht;
+	const char* pin = pre_selected_pin.length() > 0 ? pre_selected_pin.data() : nullptr;
+	int new_pin = wpas_p2p_connect(
+	    wpa_s, peer_address.data(), pin, wps_method,
+	    persistent, false, join_existing_group, false, go_intent_signed, 0, 0, -1,
+	    false, ht40, vht, VHT_CHANWIDTH_USE_HT, nullptr, 0);
+	if (new_pin < 0) {
+		return {{SupplicantStatusCode::FAILURE_UNKNOWN, ""}, {}};
+	}
+	std::string pin_ret;
+	if (provision_method == WpsProvisionMethod::DISPLAY &&
+	    pre_selected_pin.empty()) {
+		pin_ret = misc_utils::convertWpsPinToString(new_pin);
+	}
+	return {{SupplicantStatusCode::SUCCESS, ""}, pin_ret};
+}
+
+SupplicantStatus P2pIface::cancelConnectInternal()
+{
+	struct wpa_supplicant* wpa_s = retrieveIfacePtr();
+	if (wpas_p2p_cancel(wpa_s)) {
+		return {SupplicantStatusCode::FAILURE_UNKNOWN, ""};
+	}
+	return {SupplicantStatusCode::SUCCESS, ""};
+}
+
+SupplicantStatus P2pIface::provisionDiscoveryInternal(
+    const std::array<uint8_t, 6>& peer_address,
+    ISupplicantP2pIface::WpsProvisionMethod provision_method)
+{
+	struct wpa_supplicant* wpa_s = retrieveIfacePtr();
+	p2ps_provision* prov_param;
+	const char* config_method_str = nullptr;
+	switch (provision_method) {
+	case WpsProvisionMethod::PBC:
+		config_method_str = kConfigMethodStrPbc;
+		break;
+	case WpsProvisionMethod::DISPLAY:
+		config_method_str = kConfigMethodStrDisplay;
+		break;
+	case WpsProvisionMethod::KEYPAD:
+		config_method_str = kConfigMethodStrKeypad;
+		break;
+	}
+	if (wpas_p2p_prov_disc(
+		wpa_s, peer_address.data(), config_method_str,
+		WPAS_P2P_PD_FOR_GO_NEG, nullptr)) {
+		return {SupplicantStatusCode::FAILURE_UNKNOWN, ""};
+	}
+	return {SupplicantStatusCode::SUCCESS, ""};
+}
+
+SupplicantStatus P2pIface::addGroupInternal(
+    bool persistent, SupplicantNetworkId persistent_network_id)
+{
+	struct wpa_supplicant* wpa_s = retrieveIfacePtr();
+	int vht = wpa_s->conf->p2p_go_vht;
+	int ht40 = wpa_s->conf->p2p_go_ht40 || vht;
+	struct wpa_ssid* ssid =
+	    wpa_config_get_network(wpa_s->conf, persistent_network_id);
+	if (ssid == NULL) {
+		if (wpas_p2p_group_add(
+			wpa_s, persistent, 0, 0, ht40, vht,
+			VHT_CHANWIDTH_USE_HT)) {
+			return {SupplicantStatusCode::FAILURE_UNKNOWN, ""};
+		} else {
+			return {SupplicantStatusCode::SUCCESS, ""};
+		}
+	} else if (ssid->disabled == 2) {
+		if (wpas_p2p_group_add_persistent(
+			wpa_s, ssid, 0, 0, 0, 0, ht40, vht,
+			VHT_CHANWIDTH_USE_HT, NULL, 0, 0)) {
+			return {SupplicantStatusCode::FAILURE_NETWORK_UNKNOWN,
+				""};
+		} else {
+			return {SupplicantStatusCode::SUCCESS, ""};
+		}
+	}
+	return {SupplicantStatusCode::FAILURE_UNKNOWN, ""};
+}
+
+SupplicantStatus P2pIface::removeGroupInternal(const std::string& group_ifname)
+{
+	struct wpa_supplicant* wpa_group_s =
+	    retrieveGroupIfacePtr(group_ifname);
+	if (!wpa_group_s) {
+		return {SupplicantStatusCode::FAILURE_IFACE_UNKNOWN, ""};
+	}
+	if (wpas_p2p_group_remove(wpa_group_s, group_ifname.c_str())) {
+		return {SupplicantStatusCode::FAILURE_UNKNOWN, ""};
+	}
+	return {SupplicantStatusCode::SUCCESS, ""};
+}
+
+SupplicantStatus P2pIface::rejectInternal(
+    const std::array<uint8_t, 6>& peer_address)
+{
+	struct wpa_supplicant* wpa_s = retrieveIfacePtr();
+	if (wpa_s->global->p2p_disabled || wpa_s->global->p2p == NULL) {
+		return {SupplicantStatusCode::FAILURE_IFACE_DISABLED, ""};
+	}
+	if (wpas_p2p_reject(wpa_s, peer_address.data())) {
+		return {SupplicantStatusCode::FAILURE_UNKNOWN, ""};
+	}
+	return {SupplicantStatusCode::SUCCESS, ""};
+}
+
+SupplicantStatus P2pIface::inviteInternal(
+    const std::string& group_ifname,
+    const std::array<uint8_t, 6>& go_device_address,
+    const std::array<uint8_t, 6>& peer_address)
+{
+	struct wpa_supplicant* wpa_s = retrieveIfacePtr();
+	if (wpas_p2p_invite_group(
+		wpa_s, group_ifname.c_str(), peer_address.data(),
+		go_device_address.data())) {
+		return {SupplicantStatusCode::FAILURE_UNKNOWN, ""};
+	}
+	return {SupplicantStatusCode::SUCCESS, ""};
+}
+
+SupplicantStatus P2pIface::reinvokeInternal(
+    SupplicantNetworkId persistent_network_id,
+    const std::array<uint8_t, 6>& peer_address)
+{
+	struct wpa_supplicant* wpa_s = retrieveIfacePtr();
+	int vht = wpa_s->conf->p2p_go_vht;
+	int ht40 = wpa_s->conf->p2p_go_ht40 || vht;
+	struct wpa_ssid* ssid =
+	    wpa_config_get_network(wpa_s->conf, persistent_network_id);
+	if (ssid == NULL || ssid->disabled != 2) {
+		return {SupplicantStatusCode::FAILURE_NETWORK_UNKNOWN, ""};
+	}
+	if (wpas_p2p_invite(
+		wpa_s, peer_address.data(), ssid, NULL, 0, 0, ht40, vht,
+		VHT_CHANWIDTH_USE_HT, 0)) {
+		return {SupplicantStatusCode::FAILURE_UNKNOWN, ""};
+	}
+	return {SupplicantStatusCode::SUCCESS, ""};
+}
+
+SupplicantStatus P2pIface::configureExtListenInternal(
+    uint32_t period_in_millis, uint32_t interval_in_millis)
+{
+	struct wpa_supplicant* wpa_s = retrieveIfacePtr();
+	if (wpas_p2p_ext_listen(wpa_s, period_in_millis, interval_in_millis)) {
+		return {SupplicantStatusCode::FAILURE_UNKNOWN, ""};
+	}
+	return {SupplicantStatusCode::SUCCESS, ""};
+}
+
+SupplicantStatus P2pIface::setListenChannelInternal(
+    uint32_t channel, uint32_t operating_class)
+{
+	struct wpa_supplicant* wpa_s = retrieveIfacePtr();
+	if (p2p_set_listen_channel(
+		wpa_s->global->p2p, operating_class, channel, 1)) {
+		return {SupplicantStatusCode::FAILURE_UNKNOWN, ""};
+	}
+	return {SupplicantStatusCode::SUCCESS, ""};
+}
+
+SupplicantStatus P2pIface::setDisallowedFrequenciesInternal(
+    const std::vector<FreqRange>& ranges)
+{
+	struct wpa_supplicant* wpa_s = retrieveIfacePtr();
+	using DestT = struct wpa_freq_range_list::wpa_freq_range;
+	DestT* freq_ranges = nullptr;
+	// Empty ranges is used to enable all frequencies.
+	if (ranges.size() != 0) {
+		freq_ranges =
+		    static_cast<DestT*>(os_malloc(sizeof(DestT) * ranges.size()));
+		if (!freq_ranges) {
+			return {SupplicantStatusCode::FAILURE_UNKNOWN, ""};
+		}
+		uint32_t i = 0;
+		for (const auto& range : ranges) {
+			freq_ranges[i].min = range.min;
+			freq_ranges[i].max = range.max;
+			i++;
+		}
+	}
+
+	os_free(wpa_s->global->p2p_disallow_freq.range);
+	wpa_s->global->p2p_disallow_freq.range = freq_ranges;
+	wpa_s->global->p2p_disallow_freq.num = ranges.size();
+	wpas_p2p_update_channel_list(wpa_s, WPAS_P2P_CHANNEL_UPDATE_DISALLOW);
+	return {SupplicantStatusCode::SUCCESS, ""};
+}
+
+std::pair<SupplicantStatus, std::vector<uint8_t>> P2pIface::getSsidInternal(
+    const std::array<uint8_t, 6>& peer_address)
+{
+	struct wpa_supplicant* wpa_s = retrieveIfacePtr();
+	const struct p2p_peer_info* info =
+	    p2p_get_peer_info(wpa_s->global->p2p, peer_address.data(), 0);
+	if (!info) {
+		return {{SupplicantStatusCode::FAILURE_UNKNOWN, ""}, {}};
+	}
+	const struct p2p_device* dev =
+	    reinterpret_cast<const struct p2p_device*>(
+		(reinterpret_cast<const uint8_t*>(info)) -
+		offsetof(struct p2p_device, info));
+	std::vector<uint8_t> ssid;
+	if (dev && dev->oper_ssid_len) {
+		ssid.assign(
+		    dev->oper_ssid, dev->oper_ssid + dev->oper_ssid_len);
+	}
+	return {{SupplicantStatusCode::SUCCESS, ""}, ssid};
+}
+
+std::pair<SupplicantStatus, uint32_t> P2pIface::getGroupCapabilityInternal(
+    const std::array<uint8_t, 6>& peer_address)
+{
+	struct wpa_supplicant* wpa_s = retrieveIfacePtr();
+	const struct p2p_peer_info* info =
+	    p2p_get_peer_info(wpa_s->global->p2p, peer_address.data(), 0);
+	if (!info) {
+		return {{SupplicantStatusCode::FAILURE_UNKNOWN, ""}, {}};
+	}
+	return {{SupplicantStatusCode::SUCCESS, ""}, info->group_capab};
+}
+
+SupplicantStatus P2pIface::addBonjourServiceInternal(
+    const std::vector<uint8_t>& query, const std::vector<uint8_t>& response)
+{
+	struct wpa_supplicant* wpa_s = retrieveIfacePtr();
+	auto query_buf = misc_utils::convertVectorToWpaBuf(query);
+	auto response_buf = misc_utils::convertVectorToWpaBuf(response);
+	if (!query_buf || !response_buf) {
+		return {SupplicantStatusCode::FAILURE_UNKNOWN, ""};
+	}
+	if (wpas_p2p_service_add_bonjour(
+		wpa_s, query_buf.get(), response_buf.get())) {
+		return {SupplicantStatusCode::FAILURE_UNKNOWN, ""};
+	}
+	// If successful, the wpabuf is referenced internally and hence should
+	// not be freed.
+	query_buf.release();
+	response_buf.release();
+	return {SupplicantStatusCode::SUCCESS, ""};
+}
+
+SupplicantStatus P2pIface::removeBonjourServiceInternal(
+    const std::vector<uint8_t>& query)
+{
+	struct wpa_supplicant* wpa_s = retrieveIfacePtr();
+	auto query_buf = misc_utils::convertVectorToWpaBuf(query);
+	if (!query_buf) {
+		return {SupplicantStatusCode::FAILURE_UNKNOWN, ""};
+	}
+	if (wpas_p2p_service_del_bonjour(wpa_s, query_buf.get())) {
+		return {SupplicantStatusCode::FAILURE_UNKNOWN, ""};
+	}
+	return {SupplicantStatusCode::SUCCESS, ""};
+}
+
+SupplicantStatus P2pIface::addUpnpServiceInternal(
+    uint32_t version, const std::string& service_name)
+{
+	struct wpa_supplicant* wpa_s = retrieveIfacePtr();
+	if (wpas_p2p_service_add_upnp(wpa_s, version, service_name.c_str())) {
+		return {SupplicantStatusCode::FAILURE_UNKNOWN, ""};
+	}
+	return {SupplicantStatusCode::SUCCESS, ""};
+}
+
+SupplicantStatus P2pIface::removeUpnpServiceInternal(
+    uint32_t version, const std::string& service_name)
+{
+	struct wpa_supplicant* wpa_s = retrieveIfacePtr();
+	if (wpas_p2p_service_del_upnp(wpa_s, version, service_name.c_str())) {
+		return {SupplicantStatusCode::FAILURE_UNKNOWN, ""};
+	}
+	return {SupplicantStatusCode::SUCCESS, ""};
+}
+
+SupplicantStatus P2pIface::flushServicesInternal()
+{
+	struct wpa_supplicant* wpa_s = retrieveIfacePtr();
+	wpas_p2p_service_flush(wpa_s);
+	return {SupplicantStatusCode::SUCCESS, ""};
+}
+
+std::pair<SupplicantStatus, uint64_t> P2pIface::requestServiceDiscoveryInternal(
+    const std::array<uint8_t, 6>& peer_address,
+    const std::vector<uint8_t>& query)
+{
+	struct wpa_supplicant* wpa_s = retrieveIfacePtr();
+	auto query_buf = misc_utils::convertVectorToWpaBuf(query);
+	if (!query_buf) {
+		return {{SupplicantStatusCode::FAILURE_UNKNOWN, ""}, {}};
+	}
+	const uint8_t* dst_addr = is_zero_ether_addr(peer_address.data())
+				      ? nullptr
+				      : peer_address.data();
+	uint64_t identifier =
+	    wpas_p2p_sd_request(wpa_s, dst_addr, query_buf.get());
+	if (identifier == 0) {
+		return {{SupplicantStatusCode::FAILURE_UNKNOWN, ""}, {}};
+	}
+	return {{SupplicantStatusCode::SUCCESS, ""}, identifier};
+}
+
+SupplicantStatus P2pIface::cancelServiceDiscoveryInternal(uint64_t identifier)
+{
+	struct wpa_supplicant* wpa_s = retrieveIfacePtr();
+	if (wpas_p2p_sd_cancel_request(wpa_s, identifier)) {
+		return {SupplicantStatusCode::FAILURE_UNKNOWN, ""};
+	}
+	return {SupplicantStatusCode::SUCCESS, ""};
+}
+
+SupplicantStatus P2pIface::setMiracastModeInternal(
+    ISupplicantP2pIface::MiracastMode mode)
+{
+	struct wpa_supplicant* wpa_s = retrieveIfacePtr();
+	uint8_t mode_internal = convertHidlMiracastModeToInternal(mode);
+	const std::string cmd_str =
+	    kSetMiracastMode + std::to_string(mode_internal);
+	std::vector<char> cmd(
+	    cmd_str.c_str(), cmd_str.c_str() + cmd_str.size() + 1);
+	char driver_cmd_reply_buf[4096] = {};
+	if (wpa_drv_driver_cmd(
+		wpa_s, cmd.data(), driver_cmd_reply_buf,
+		sizeof(driver_cmd_reply_buf))) {
+		return {SupplicantStatusCode::FAILURE_UNKNOWN, ""};
+	}
+	return {SupplicantStatusCode::SUCCESS, ""};
+}
+
+SupplicantStatus P2pIface::startWpsPbcInternal(
+    const std::string& group_ifname, const std::array<uint8_t, 6>& bssid)
+{
+	struct wpa_supplicant* wpa_group_s =
+	    retrieveGroupIfacePtr(group_ifname);
+	if (!wpa_group_s) {
+		return {SupplicantStatusCode::FAILURE_IFACE_UNKNOWN, ""};
+	}
+	const uint8_t* bssid_addr =
+	    is_zero_ether_addr(bssid.data()) ? nullptr : bssid.data();
+#ifdef CONFIG_AP
+	if (wpa_group_s->ap_iface) {
+		if (wpa_supplicant_ap_wps_pbc(wpa_group_s, bssid_addr, NULL)) {
+			return {SupplicantStatusCode::FAILURE_UNKNOWN, ""};
+		}
+		return {SupplicantStatusCode::SUCCESS, ""};
+	}
+#endif /* CONFIG_AP */
+	if (wpas_wps_start_pbc(wpa_group_s, bssid_addr, 0)) {
+		return {SupplicantStatusCode::FAILURE_UNKNOWN, ""};
+	}
+	return {SupplicantStatusCode::SUCCESS, ""};
+}
+
+SupplicantStatus P2pIface::startWpsPinKeypadInternal(
+    const std::string& group_ifname, const std::string& pin)
+{
+	struct wpa_supplicant* wpa_group_s =
+	    retrieveGroupIfacePtr(group_ifname);
+	if (!wpa_group_s) {
+		return {SupplicantStatusCode::FAILURE_IFACE_UNKNOWN, ""};
+	}
+#ifdef CONFIG_AP
+	if (wpa_group_s->ap_iface) {
+		if (wpa_supplicant_ap_wps_pin(
+				wpa_group_s, nullptr, pin.c_str(), nullptr, 0, 0) < 0) {
+			return {SupplicantStatusCode::FAILURE_UNKNOWN, ""};
+		}
+		return {SupplicantStatusCode::SUCCESS, ""};
+	}
+#endif /* CONFIG_AP */
+	if (wpas_wps_start_pin(
+		wpa_group_s, nullptr, pin.c_str(), 0, DEV_PW_DEFAULT)) {
+		return {SupplicantStatusCode::FAILURE_UNKNOWN, ""};
+	}
+	return {SupplicantStatusCode::SUCCESS, ""};
+}
+
+std::pair<SupplicantStatus, std::string> P2pIface::startWpsPinDisplayInternal(
+    const std::string& group_ifname, const std::array<uint8_t, 6>& bssid)
+{
+	struct wpa_supplicant* wpa_group_s =
+	    retrieveGroupIfacePtr(group_ifname);
+	if (!wpa_group_s) {
+		return {{SupplicantStatusCode::FAILURE_IFACE_UNKNOWN, ""}, ""};
+	}
+	const uint8_t* bssid_addr =
+	    is_zero_ether_addr(bssid.data()) ? nullptr : bssid.data();
+	int pin = wpas_wps_start_pin(
+	    wpa_group_s, bssid_addr, nullptr, 0, DEV_PW_DEFAULT);
+	if (pin < 0) {
+		return {{SupplicantStatusCode::FAILURE_UNKNOWN, ""}, ""};
+	}
+	return {{SupplicantStatusCode::SUCCESS, ""},
+		misc_utils::convertWpsPinToString(pin)};
+}
+
+SupplicantStatus P2pIface::cancelWpsInternal(const std::string& group_ifname)
+{
+	struct wpa_supplicant* wpa_group_s =
+	    retrieveGroupIfacePtr(group_ifname);
+	if (!wpa_group_s) {
+		return {SupplicantStatusCode::FAILURE_IFACE_UNKNOWN, ""};
+	}
+	if (wpas_wps_cancel(wpa_group_s)) {
+		return {SupplicantStatusCode::FAILURE_UNKNOWN, ""};
+	}
+	return {SupplicantStatusCode::SUCCESS, ""};
+}
+
+SupplicantStatus P2pIface::setWpsDeviceNameInternal(const std::string& name)
+{
+	return iface_config_utils::setWpsDeviceName(retrieveIfacePtr(), name);
+}
+
+SupplicantStatus P2pIface::setWpsDeviceTypeInternal(
+    const std::array<uint8_t, 8>& type)
+{
+	return iface_config_utils::setWpsDeviceType(retrieveIfacePtr(), type);
+}
+
+SupplicantStatus P2pIface::setWpsManufacturerInternal(
+    const std::string& manufacturer)
+{
+	return iface_config_utils::setWpsManufacturer(
+	    retrieveIfacePtr(), manufacturer);
+}
+
+SupplicantStatus P2pIface::setWpsModelNameInternal(
+    const std::string& model_name)
+{
+	return iface_config_utils::setWpsModelName(
+	    retrieveIfacePtr(), model_name);
+}
+
+SupplicantStatus P2pIface::setWpsModelNumberInternal(
+    const std::string& model_number)
+{
+	return iface_config_utils::setWpsModelNumber(
+	    retrieveIfacePtr(), model_number);
+}
+
+SupplicantStatus P2pIface::setWpsSerialNumberInternal(
+    const std::string& serial_number)
+{
+	return iface_config_utils::setWpsSerialNumber(
+	    retrieveIfacePtr(), serial_number);
+}
+
+SupplicantStatus P2pIface::setWpsConfigMethodsInternal(uint16_t config_methods)
+{
+	return iface_config_utils::setWpsConfigMethods(
+	    retrieveIfacePtr(), config_methods);
+}
+
+SupplicantStatus P2pIface::enableWfdInternal(bool enable)
+{
+	struct wpa_supplicant* wpa_s = retrieveIfacePtr();
+	wifi_display_enable(wpa_s->global, enable);
+	return {SupplicantStatusCode::SUCCESS, ""};
+}
+
+SupplicantStatus P2pIface::setWfdDeviceInfoInternal(
+    const std::array<uint8_t, 6>& info)
+{
+	struct wpa_supplicant* wpa_s = retrieveIfacePtr();
+	std::vector<char> wfd_device_info_hex(info.size() * 2 + 1);
+	wpa_snprintf_hex(
+	    wfd_device_info_hex.data(), wfd_device_info_hex.size(), info.data(),
+	    info.size());
+	// |wifi_display_subelem_set| expects the first 2 bytes
+	// to hold the lenght of the subelement. In this case it's
+	// fixed to 6, so prepend that.
+	std::string wfd_device_info_set_cmd_str =
+	    std::to_string(kWfdDeviceInfoSubelemId) + " " +
+	    kWfdDeviceInfoSubelemLenHexStr + wfd_device_info_hex.data();
+	std::vector<char> wfd_device_info_set_cmd(
+	    wfd_device_info_set_cmd_str.c_str(),
+	    wfd_device_info_set_cmd_str.c_str() +
+		wfd_device_info_set_cmd_str.size() + 1);
+	if (wifi_display_subelem_set(
+		wpa_s->global, wfd_device_info_set_cmd.data())) {
+		return {SupplicantStatusCode::FAILURE_UNKNOWN, ""};
+	}
+	return {SupplicantStatusCode::SUCCESS, ""};
+}
+
+std::pair<SupplicantStatus, std::vector<uint8_t>>
+P2pIface::createNfcHandoverRequestMessageInternal()
+{
+	struct wpa_supplicant* wpa_s = retrieveIfacePtr();
+	auto buf = misc_utils::createWpaBufUniquePtr(
+	    wpas_p2p_nfc_handover_req(wpa_s, 1));
+	if (!buf) {
+		return {{SupplicantStatusCode::FAILURE_UNKNOWN, ""}, {}};
+	}
+	return {{SupplicantStatusCode::SUCCESS, ""},
+		misc_utils::convertWpaBufToVector(buf.get())};
+}
+
+std::pair<SupplicantStatus, std::vector<uint8_t>>
+P2pIface::createNfcHandoverSelectMessageInternal()
+{
+	struct wpa_supplicant* wpa_s = retrieveIfacePtr();
+	auto buf = misc_utils::createWpaBufUniquePtr(
+	    wpas_p2p_nfc_handover_sel(wpa_s, 1, 0));
+	if (!buf) {
+		return {{SupplicantStatusCode::FAILURE_UNKNOWN, ""}, {}};
+	}
+	return {{SupplicantStatusCode::SUCCESS, ""},
+		misc_utils::convertWpaBufToVector(buf.get())};
+}
+
+SupplicantStatus P2pIface::reportNfcHandoverResponseInternal(
+    const std::vector<uint8_t>& request)
+{
+	struct wpa_supplicant* wpa_s = retrieveIfacePtr();
+	auto req = misc_utils::convertVectorToWpaBuf(request);
+	auto sel = misc_utils::convertVectorToWpaBuf(std::vector<uint8_t>{0});
+	if (!req || !sel) {
+		return {SupplicantStatusCode::FAILURE_UNKNOWN, ""};
+	}
+
+	if (wpas_p2p_nfc_report_handover(wpa_s, 0, req.get(), sel.get(), 0)) {
+		return {SupplicantStatusCode::FAILURE_UNKNOWN, ""};
+	}
+	return {SupplicantStatusCode::SUCCESS, ""};
+}
+
+SupplicantStatus P2pIface::reportNfcHandoverInitiationInternal(
+    const std::vector<uint8_t>& select)
+{
+	struct wpa_supplicant* wpa_s = retrieveIfacePtr();
+	auto req = misc_utils::convertVectorToWpaBuf(std::vector<uint8_t>{0});
+	auto sel = misc_utils::convertVectorToWpaBuf(select);
+	if (!req || !sel) {
+		return {SupplicantStatusCode::FAILURE_UNKNOWN, ""};
+	}
+
+	if (wpas_p2p_nfc_report_handover(wpa_s, 1, req.get(), sel.get(), 0)) {
+		return {SupplicantStatusCode::FAILURE_UNKNOWN, ""};
+	}
+	return {SupplicantStatusCode::SUCCESS, ""};
+}
+
+SupplicantStatus P2pIface::saveConfigInternal()
+{
+	struct wpa_supplicant* wpa_s = retrieveIfacePtr();
+	if (!wpa_s->conf->update_config) {
+		return {SupplicantStatusCode::FAILURE_UNKNOWN, ""};
+	}
+	if (wpa_config_write(wpa_s->confname, wpa_s->conf)) {
+		return {SupplicantStatusCode::FAILURE_UNKNOWN, ""};
+	}
+	return {SupplicantStatusCode::SUCCESS, ""};
+}
+
+/**
+ * Retrieve the underlying |wpa_supplicant| struct
+ * pointer for this iface.
+ * If the underlying iface is removed, then all RPC method calls on this object
+ * will return failure.
+ */
+wpa_supplicant* P2pIface::retrieveIfacePtr()
+{
+	return wpa_supplicant_get_iface(wpa_global_, ifname_.c_str());
+}
+
+/**
+ * Retrieve the underlying |wpa_supplicant| struct
+ * pointer for this group iface.
+ */
+wpa_supplicant* P2pIface::retrieveGroupIfacePtr(const std::string& group_ifname)
+{
+	return wpa_supplicant_get_iface(wpa_global_, group_ifname.c_str());
+}
+
+}  // namespace implementation
+}  // namespace V1_1
+}  // namespace wifi
+}  // namespace supplicant
+}  // namespace hardware
+}  // namespace android
diff --git a/wpa_supplicant/hidl/1.1/p2p_iface.h b/wpa_supplicant/hidl/1.1/p2p_iface.h
new file mode 100644
index 0000000..019e534
--- /dev/null
+++ b/wpa_supplicant/hidl/1.1/p2p_iface.h
@@ -0,0 +1,314 @@
+/*
+ * hidl interface for wpa_supplicant daemon
+ * Copyright (c) 2004-2016, Jouni Malinen <j@w1.fi>
+ * Copyright (c) 2004-2016, Roshan Pius <rpius@google.com>
+ *
+ * This software may be distributed under the terms of the BSD license.
+ * See README for more details.
+ */
+
+#ifndef WPA_SUPPLICANT_HIDL_P2P_IFACE_H
+#define WPA_SUPPLICANT_HIDL_P2P_IFACE_H
+
+#include <array>
+#include <vector>
+
+#include <android-base/macros.h>
+
+#include <android/hardware/wifi/supplicant/1.0/ISupplicantP2pIface.h>
+#include <android/hardware/wifi/supplicant/1.0/ISupplicantP2pIfaceCallback.h>
+#include <android/hardware/wifi/supplicant/1.0/ISupplicantP2pNetwork.h>
+
+extern "C" {
+#include "utils/common.h"
+#include "utils/includes.h"
+#include "p2p/p2p.h"
+#include "p2p/p2p_i.h"
+#include "p2p_supplicant.h"
+#include "p2p_supplicant.h"
+#include "config.h"
+}
+
+namespace android {
+namespace hardware {
+namespace wifi {
+namespace supplicant {
+namespace V1_1 {
+namespace implementation {
+using namespace android::hardware::wifi::supplicant::V1_0;
+
+/**
+ * Implementation of P2pIface hidl object. Each unique hidl
+ * object is used for control operations on a specific interface
+ * controlled by wpa_supplicant.
+ */
+class P2pIface : public ISupplicantP2pIface
+{
+public:
+	P2pIface(struct wpa_global* wpa_global, const char ifname[]);
+	~P2pIface() override = default;
+	// Refer to |StaIface::invalidate()|.
+	void invalidate();
+	bool isValid();
+
+	// Hidl methods exposed.
+	Return<void> getName(getName_cb _hidl_cb) override;
+	Return<void> getType(getType_cb _hidl_cb) override;
+	Return<void> addNetwork(addNetwork_cb _hidl_cb) override;
+	Return<void> removeNetwork(
+	    SupplicantNetworkId id, removeNetwork_cb _hidl_cb) override;
+	Return<void> getNetwork(
+	    SupplicantNetworkId id, getNetwork_cb _hidl_cb) override;
+	Return<void> listNetworks(listNetworks_cb _hidl_cb) override;
+	Return<void> registerCallback(
+	    const sp<ISupplicantP2pIfaceCallback>& callback,
+	    registerCallback_cb _hidl_cb) override;
+	Return<void> getDeviceAddress(getDeviceAddress_cb _hidl_cb) override;
+	Return<void> setSsidPostfix(
+	    const hidl_vec<uint8_t>& postfix,
+	    setSsidPostfix_cb _hidl_cb) override;
+	Return<void> setGroupIdle(
+	    const hidl_string& group_ifname, uint32_t timeout_in_sec,
+	    setGroupIdle_cb _hidl_cb) override;
+	Return<void> setPowerSave(
+	    const hidl_string& group_ifname, bool enable,
+	    setPowerSave_cb _hidl_cb) override;
+	Return<void> find(uint32_t timeout_in_sec, find_cb _hidl_cb) override;
+	Return<void> stopFind(stopFind_cb _hidl_cb) override;
+	Return<void> flush(flush_cb _hidl_cb) override;
+	Return<void> connect(
+	    const hidl_array<uint8_t, 6>& peer_address,
+	    ISupplicantP2pIface::WpsProvisionMethod provision_method,
+	    const hidl_string& pre_selected_pin, bool join_existing_group,
+	    bool persistent, uint32_t go_intent, connect_cb _hidl_cb) override;
+	Return<void> cancelConnect(cancelConnect_cb _hidl_cb) override;
+	Return<void> provisionDiscovery(
+	    const hidl_array<uint8_t, 6>& peer_address,
+	    ISupplicantP2pIface::WpsProvisionMethod provision_method,
+	    provisionDiscovery_cb _hidl_cb) override;
+	Return<void> addGroup(
+	    bool persistent, SupplicantNetworkId persistent_network_id,
+	    addGroup_cb _hidl_cb) override;
+	Return<void> removeGroup(
+	    const hidl_string& group_ifname, removeGroup_cb _hidl_cb) override;
+	Return<void> reject(
+	    const hidl_array<uint8_t, 6>& peer_address,
+	    reject_cb _hidl_cb) override;
+	Return<void> invite(
+	    const hidl_string& group_ifname,
+	    const hidl_array<uint8_t, 6>& go_device_address,
+	    const hidl_array<uint8_t, 6>& peer_address,
+	    invite_cb _hidl_cb) override;
+	Return<void> reinvoke(
+	    SupplicantNetworkId persistent_network_id,
+	    const hidl_array<uint8_t, 6>& peer_address,
+	    reinvoke_cb _hidl_cb) override;
+	Return<void> configureExtListen(
+	    uint32_t period_in_millis, uint32_t interval_in_millis,
+	    configureExtListen_cb _hidl_cb) override;
+	Return<void> setListenChannel(
+	    uint32_t channel, uint32_t operating_class,
+	    setListenChannel_cb _hidl_cb) override;
+	Return<void> setDisallowedFrequencies(
+	    const hidl_vec<FreqRange>& ranges,
+	    setDisallowedFrequencies_cb _hidl_cb) override;
+	Return<void> getSsid(
+	    const hidl_array<uint8_t, 6>& peer_address,
+	    getSsid_cb _hidl_cb) override;
+	Return<void> getGroupCapability(
+	    const hidl_array<uint8_t, 6>& peer_address,
+	    getGroupCapability_cb _hidl_cb) override;
+	Return<void> addBonjourService(
+	    const hidl_vec<uint8_t>& query, const hidl_vec<uint8_t>& response,
+	    addBonjourService_cb _hidl_cb) override;
+	Return<void> removeBonjourService(
+	    const hidl_vec<uint8_t>& query,
+	    removeBonjourService_cb _hidl_cb) override;
+	Return<void> addUpnpService(
+	    uint32_t version, const hidl_string& service_name,
+	    addUpnpService_cb _hidl_cb) override;
+	Return<void> removeUpnpService(
+	    uint32_t version, const hidl_string& service_name,
+	    removeUpnpService_cb _hidl_cb) override;
+	Return<void> flushServices(flushServices_cb _hidl_cb) override;
+	Return<void> requestServiceDiscovery(
+	    const hidl_array<uint8_t, 6>& peer_address,
+	    const hidl_vec<uint8_t>& query,
+	    requestServiceDiscovery_cb _hidl_cb) override;
+	Return<void> cancelServiceDiscovery(
+	    uint64_t identifier, cancelServiceDiscovery_cb _hidl_cb) override;
+	Return<void> setMiracastMode(
+	    ISupplicantP2pIface::MiracastMode mode,
+	    setMiracastMode_cb _hidl_cb) override;
+	Return<void> startWpsPbc(
+	    const hidl_string& groupIfName, const hidl_array<uint8_t, 6>& bssid,
+	    startWpsPbc_cb _hidl_cb) override;
+	Return<void> startWpsPinKeypad(
+	    const hidl_string& groupIfName, const hidl_string& pin,
+	    startWpsPinKeypad_cb _hidl_cb) override;
+	Return<void> startWpsPinDisplay(
+	    const hidl_string& groupIfName, const hidl_array<uint8_t, 6>& bssid,
+	    startWpsPinDisplay_cb _hidl_cb) override;
+	Return<void> cancelWps(
+	    const hidl_string& groupIfName, cancelWps_cb _hidl_cb) override;
+	Return<void> setWpsDeviceName(
+	    const hidl_string& name, setWpsDeviceName_cb _hidl_cb) override;
+	Return<void> setWpsDeviceType(
+	    const hidl_array<uint8_t, 8>& type,
+	    setWpsDeviceType_cb _hidl_cb) override;
+	Return<void> setWpsManufacturer(
+	    const hidl_string& manufacturer,
+	    setWpsManufacturer_cb _hidl_cb) override;
+	Return<void> setWpsModelName(
+	    const hidl_string& model_name,
+	    setWpsModelName_cb _hidl_cb) override;
+	Return<void> setWpsModelNumber(
+	    const hidl_string& model_number,
+	    setWpsModelNumber_cb _hidl_cb) override;
+	Return<void> setWpsSerialNumber(
+	    const hidl_string& serial_number,
+	    setWpsSerialNumber_cb _hidl_cb) override;
+	Return<void> setWpsConfigMethods(
+	    uint16_t config_methods, setWpsConfigMethods_cb _hidl_cb) override;
+	Return<void> enableWfd(bool enable, enableWfd_cb _hidl_cb) override;
+	Return<void> setWfdDeviceInfo(
+	    const hidl_array<uint8_t, 6>& info,
+	    setWfdDeviceInfo_cb _hidl_cb) override;
+	Return<void> createNfcHandoverRequestMessage(
+	    createNfcHandoverRequestMessage_cb _hidl_cb) override;
+	Return<void> createNfcHandoverSelectMessage(
+	    createNfcHandoverSelectMessage_cb _hidl_cb) override;
+	Return<void> reportNfcHandoverResponse(
+	    const hidl_vec<uint8_t>& request,
+	    reportNfcHandoverResponse_cb _hidl_cb) override;
+	Return<void> reportNfcHandoverInitiation(
+	    const hidl_vec<uint8_t>& select,
+	    reportNfcHandoverInitiation_cb _hidl_cb) override;
+	Return<void> saveConfig(saveConfig_cb _hidl_cb) override;
+
+private:
+	// Corresponding worker functions for the HIDL methods.
+	std::pair<SupplicantStatus, std::string> getNameInternal();
+	std::pair<SupplicantStatus, IfaceType> getTypeInternal();
+	std::pair<SupplicantStatus, sp<ISupplicantP2pNetwork>>
+	addNetworkInternal();
+	SupplicantStatus removeNetworkInternal(SupplicantNetworkId id);
+	std::pair<SupplicantStatus, sp<ISupplicantP2pNetwork>>
+	getNetworkInternal(SupplicantNetworkId id);
+	std::pair<SupplicantStatus, std::vector<SupplicantNetworkId>>
+	listNetworksInternal();
+	SupplicantStatus registerCallbackInternal(
+	    const sp<ISupplicantP2pIfaceCallback>& callback);
+	std::pair<SupplicantStatus, std::array<uint8_t, 6>>
+	getDeviceAddressInternal();
+	SupplicantStatus setSsidPostfixInternal(
+	    const std::vector<uint8_t>& postfix);
+	SupplicantStatus setGroupIdleInternal(
+	    const std::string& group_ifname, uint32_t timeout_in_sec);
+	SupplicantStatus setPowerSaveInternal(
+	    const std::string& group_ifname, bool enable);
+	SupplicantStatus findInternal(uint32_t timeout_in_sec);
+	SupplicantStatus stopFindInternal();
+	SupplicantStatus flushInternal();
+	std::pair<SupplicantStatus, std::string> connectInternal(
+	    const std::array<uint8_t, 6>& peer_address,
+	    ISupplicantP2pIface::WpsProvisionMethod provision_method,
+	    const std::string& pre_selected_pin, bool join_existing_group,
+	    bool persistent, uint32_t go_intent);
+	SupplicantStatus cancelConnectInternal();
+	SupplicantStatus provisionDiscoveryInternal(
+	    const std::array<uint8_t, 6>& peer_address,
+	    ISupplicantP2pIface::WpsProvisionMethod provision_method);
+	SupplicantStatus addGroupInternal(
+	    bool persistent, SupplicantNetworkId persistent_network_id);
+	SupplicantStatus removeGroupInternal(const std::string& group_ifname);
+	SupplicantStatus rejectInternal(
+	    const std::array<uint8_t, 6>& peer_address);
+	SupplicantStatus inviteInternal(
+	    const std::string& group_ifname,
+	    const std::array<uint8_t, 6>& go_device_address,
+	    const std::array<uint8_t, 6>& peer_address);
+	SupplicantStatus reinvokeInternal(
+	    SupplicantNetworkId persistent_network_id,
+	    const std::array<uint8_t, 6>& peer_address);
+	SupplicantStatus configureExtListenInternal(
+	    uint32_t period_in_millis, uint32_t interval_in_millis);
+	SupplicantStatus setListenChannelInternal(
+	    uint32_t channel, uint32_t operating_class);
+	SupplicantStatus setDisallowedFrequenciesInternal(
+	    const std::vector<FreqRange>& ranges);
+	std::pair<SupplicantStatus, std::vector<uint8_t>> getSsidInternal(
+	    const std::array<uint8_t, 6>& peer_address);
+	std::pair<SupplicantStatus, uint32_t> getGroupCapabilityInternal(
+	    const std::array<uint8_t, 6>& peer_address);
+	SupplicantStatus addBonjourServiceInternal(
+	    const std::vector<uint8_t>& query,
+	    const std::vector<uint8_t>& response);
+	SupplicantStatus removeBonjourServiceInternal(
+	    const std::vector<uint8_t>& query);
+	SupplicantStatus addUpnpServiceInternal(
+	    uint32_t version, const std::string& service_name);
+	SupplicantStatus removeUpnpServiceInternal(
+	    uint32_t version, const std::string& service_name);
+	SupplicantStatus flushServicesInternal();
+	std::pair<SupplicantStatus, uint64_t> requestServiceDiscoveryInternal(
+	    const std::array<uint8_t, 6>& peer_address,
+	    const std::vector<uint8_t>& query);
+	SupplicantStatus cancelServiceDiscoveryInternal(uint64_t identifier);
+	SupplicantStatus setMiracastModeInternal(
+	    ISupplicantP2pIface::MiracastMode mode);
+	SupplicantStatus startWpsPbcInternal(
+	    const std::string& group_ifname,
+	    const std::array<uint8_t, 6>& bssid);
+	SupplicantStatus startWpsPinKeypadInternal(
+	    const std::string& group_ifname, const std::string& pin);
+	std::pair<SupplicantStatus, std::string> startWpsPinDisplayInternal(
+	    const std::string& group_ifname,
+	    const std::array<uint8_t, 6>& bssid);
+	SupplicantStatus cancelWpsInternal(const std::string& group_ifname);
+	SupplicantStatus setWpsDeviceNameInternal(const std::string& name);
+	SupplicantStatus setWpsDeviceTypeInternal(
+	    const std::array<uint8_t, 8>& type);
+	SupplicantStatus setWpsManufacturerInternal(
+	    const std::string& manufacturer);
+	SupplicantStatus setWpsModelNameInternal(const std::string& model_name);
+	SupplicantStatus setWpsModelNumberInternal(
+	    const std::string& model_number);
+	SupplicantStatus setWpsSerialNumberInternal(
+	    const std::string& serial_number);
+	SupplicantStatus setWpsConfigMethodsInternal(uint16_t config_methods);
+	SupplicantStatus enableWfdInternal(bool enable);
+	SupplicantStatus setWfdDeviceInfoInternal(
+	    const std::array<uint8_t, 6>& info);
+	std::pair<SupplicantStatus, std::vector<uint8_t>>
+	createNfcHandoverRequestMessageInternal();
+	std::pair<SupplicantStatus, std::vector<uint8_t>>
+	createNfcHandoverSelectMessageInternal();
+	SupplicantStatus reportNfcHandoverResponseInternal(
+	    const std::vector<uint8_t>& request);
+	SupplicantStatus reportNfcHandoverInitiationInternal(
+	    const std::vector<uint8_t>& select);
+	SupplicantStatus saveConfigInternal();
+
+	struct wpa_supplicant* retrieveIfacePtr();
+	struct wpa_supplicant* retrieveGroupIfacePtr(
+	    const std::string& group_ifname);
+
+	// Reference to the global wpa_struct. This is assumed to be valid for
+	// the lifetime of the process.
+	struct wpa_global* wpa_global_;
+	// Name of the iface this hidl object controls
+	const std::string ifname_;
+	bool is_valid_;
+
+	DISALLOW_COPY_AND_ASSIGN(P2pIface);
+};
+
+}  // namespace implementation
+}  // namespace V1_1
+}  // namespace wifi
+}  // namespace supplicant
+}  // namespace hardware
+}  // namespace android
+
+#endif  // WPA_SUPPLICANT_HIDL_P2P_IFACE_H
diff --git a/wpa_supplicant/hidl/1.1/p2p_network.cpp b/wpa_supplicant/hidl/1.1/p2p_network.cpp
new file mode 100644
index 0000000..7458fd9
--- /dev/null
+++ b/wpa_supplicant/hidl/1.1/p2p_network.cpp
@@ -0,0 +1,257 @@
+/*
+ * hidl interface for wpa_supplicant daemon
+ * Copyright (c) 2004-2016, Jouni Malinen <j@w1.fi>
+ * Copyright (c) 2004-2016, Roshan Pius <rpius@google.com>
+ *
+ * This software may be distributed under the terms of the BSD license.
+ * See README for more details.
+ */
+
+#include "hidl_manager.h"
+#include "hidl_return_util.h"
+#include "p2p_network.h"
+
+extern "C" {
+#include "config_ssid.h"
+}
+
+namespace android {
+namespace hardware {
+namespace wifi {
+namespace supplicant {
+namespace V1_1 {
+namespace implementation {
+using hidl_return_util::validateAndCall;
+
+P2pNetwork::P2pNetwork(
+    struct wpa_global *wpa_global, const char ifname[], int network_id)
+    : wpa_global_(wpa_global),
+      ifname_(ifname),
+      network_id_(network_id),
+      is_valid_(true)
+{
+}
+
+void P2pNetwork::invalidate() { is_valid_ = false; }
+bool P2pNetwork::isValid()
+{
+	return (is_valid_ && (retrieveNetworkPtr() != nullptr));
+}
+
+Return<void> P2pNetwork::getId(getId_cb _hidl_cb)
+{
+	return validateAndCall(
+	    this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
+	    &P2pNetwork::getIdInternal, _hidl_cb);
+}
+
+Return<void> P2pNetwork::getInterfaceName(getInterfaceName_cb _hidl_cb)
+{
+	return validateAndCall(
+	    this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
+	    &P2pNetwork::getInterfaceNameInternal, _hidl_cb);
+}
+
+Return<void> P2pNetwork::getType(getType_cb _hidl_cb)
+{
+	return validateAndCall(
+	    this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
+	    &P2pNetwork::getTypeInternal, _hidl_cb);
+}
+
+Return<void> P2pNetwork::registerCallback(
+    const sp<ISupplicantP2pNetworkCallback> &callback,
+    registerCallback_cb _hidl_cb)
+{
+	return validateAndCall(
+	    this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
+	    &P2pNetwork::registerCallbackInternal, _hidl_cb, callback);
+}
+
+Return<void> P2pNetwork::getSsid(getSsid_cb _hidl_cb)
+{
+	return validateAndCall(
+	    this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
+	    &P2pNetwork::getSsidInternal, _hidl_cb);
+}
+
+Return<void> P2pNetwork::getBssid(getBssid_cb _hidl_cb)
+{
+	return validateAndCall(
+	    this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
+	    &P2pNetwork::getBssidInternal, _hidl_cb);
+}
+
+Return<void> P2pNetwork::isCurrent(isCurrent_cb _hidl_cb)
+{
+	return validateAndCall(
+	    this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
+	    &P2pNetwork::isCurrentInternal, _hidl_cb);
+}
+
+Return<void> P2pNetwork::isPersistent(isPersistent_cb _hidl_cb)
+{
+	return validateAndCall(
+	    this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
+	    &P2pNetwork::isPersistentInternal, _hidl_cb);
+}
+
+Return<void> P2pNetwork::isGo(isGo_cb _hidl_cb)
+{
+	return validateAndCall(
+	    this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
+	    &P2pNetwork::isGoInternal, _hidl_cb);
+}
+
+Return<void> P2pNetwork::setClientList(
+    const hidl_vec<hidl_array<uint8_t, 6>> &clients, setClientList_cb _hidl_cb)
+{
+	return validateAndCall(
+	    this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
+	    &P2pNetwork::setClientListInternal, _hidl_cb, clients);
+}
+
+Return<void> P2pNetwork::getClientList(getClientList_cb _hidl_cb)
+{
+	return validateAndCall(
+	    this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
+	    &P2pNetwork::getClientListInternal, _hidl_cb);
+}
+
+std::pair<SupplicantStatus, uint32_t> P2pNetwork::getIdInternal()
+{
+	return {{SupplicantStatusCode::SUCCESS, ""}, network_id_};
+}
+
+std::pair<SupplicantStatus, std::string> P2pNetwork::getInterfaceNameInternal()
+{
+	return {{SupplicantStatusCode::SUCCESS, ""}, ifname_};
+}
+
+std::pair<SupplicantStatus, IfaceType> P2pNetwork::getTypeInternal()
+{
+	return {{SupplicantStatusCode::SUCCESS, ""}, IfaceType::P2P};
+}
+
+SupplicantStatus P2pNetwork::registerCallbackInternal(
+    const sp<ISupplicantP2pNetworkCallback> &callback)
+{
+	HidlManager *hidl_manager = HidlManager::getInstance();
+	if (!hidl_manager ||
+	    hidl_manager->addP2pNetworkCallbackHidlObject(
+		ifname_, network_id_, callback)) {
+		return {SupplicantStatusCode::FAILURE_UNKNOWN, ""};
+	}
+	return {SupplicantStatusCode::SUCCESS, ""};
+}
+
+std::pair<SupplicantStatus, std::vector<uint8_t>> P2pNetwork::getSsidInternal()
+{
+	struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
+	return {{SupplicantStatusCode::SUCCESS, ""},
+		{wpa_ssid->ssid, wpa_ssid->ssid + wpa_ssid->ssid_len}};
+}
+
+std::pair<SupplicantStatus, std::array<uint8_t, 6>>
+P2pNetwork::getBssidInternal()
+{
+	struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
+	std::array<uint8_t, 6> bssid{};
+	if (wpa_ssid->bssid_set) {
+		os_memcpy(bssid.data(), wpa_ssid->bssid, ETH_ALEN);
+	}
+	return {{SupplicantStatusCode::SUCCESS, ""}, bssid};
+}
+
+std::pair<SupplicantStatus, bool> P2pNetwork::isCurrentInternal()
+{
+	struct wpa_supplicant *wpa_s = retrieveIfacePtr();
+	struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
+	return {{SupplicantStatusCode::SUCCESS, ""},
+		(wpa_s->current_ssid == wpa_ssid)};
+}
+
+std::pair<SupplicantStatus, bool> P2pNetwork::isPersistentInternal()
+{
+	struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
+	return {{SupplicantStatusCode::SUCCESS, ""}, (wpa_ssid->disabled == 2)};
+}
+
+std::pair<SupplicantStatus, bool> P2pNetwork::isGoInternal()
+{
+	struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
+	return {{SupplicantStatusCode::SUCCESS, ""},
+		(wpa_ssid->mode == wpa_ssid::wpas_mode::WPAS_MODE_P2P_GO)};
+}
+
+SupplicantStatus P2pNetwork::setClientListInternal(
+    const std::vector<hidl_array<uint8_t, 6>> &clients)
+{
+	struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
+	os_free(wpa_ssid->p2p_client_list);
+	// Internal representation uses a generic MAC addr/mask storage format
+	// (even though the mask is always 0xFF'ed for p2p_client_list). So, the
+	// first 6 bytes holds the client MAC address and the next 6 bytes are
+	// OxFF'ed.
+	wpa_ssid->p2p_client_list =
+	    (u8 *)os_malloc(ETH_ALEN * 2 * clients.size());
+	if (!wpa_ssid->p2p_client_list) {
+		return {SupplicantStatusCode::FAILURE_UNKNOWN, ""};
+	}
+	u8 *list = wpa_ssid->p2p_client_list;
+	for (const auto &client : clients) {
+		os_memcpy(list, client.data(), ETH_ALEN);
+		list += ETH_ALEN;
+		os_memset(list, 0xFF, ETH_ALEN);
+		list += ETH_ALEN;
+	}
+	wpa_ssid->num_p2p_clients = clients.size();
+	return {SupplicantStatusCode::SUCCESS, ""};
+}
+
+std::pair<SupplicantStatus, std::vector<hidl_array<uint8_t, 6>>>
+P2pNetwork::getClientListInternal()
+{
+	struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
+	if (!wpa_ssid->p2p_client_list) {
+		return {{SupplicantStatusCode::FAILURE_UNKNOWN, ""}, {}};
+	}
+	std::vector<hidl_array<uint8_t, 6>> clients;
+	u8 *list = wpa_ssid->p2p_client_list;
+	for (size_t i = 0; i < wpa_ssid->num_p2p_clients; i++) {
+		clients.emplace_back(list);
+		list += 2 * ETH_ALEN;
+	}
+	return {{SupplicantStatusCode::SUCCESS, ""}, clients};
+}
+
+/**
+ * Retrieve the underlying |wpa_ssid| struct pointer for
+ * this network.
+ * If the underlying network is removed or the interface
+ * this network belong to is removed, all RPC method calls
+ * on this object will return failure.
+ */
+struct wpa_ssid *P2pNetwork::retrieveNetworkPtr()
+{
+	wpa_supplicant *wpa_s = retrieveIfacePtr();
+	if (!wpa_s)
+		return nullptr;
+	return wpa_config_get_network(wpa_s->conf, network_id_);
+}
+
+/**
+ * Retrieve the underlying |wpa_supplicant| struct
+ * pointer for this network.
+ */
+struct wpa_supplicant *P2pNetwork::retrieveIfacePtr()
+{
+	return wpa_supplicant_get_iface(
+	    (struct wpa_global *)wpa_global_, ifname_.c_str());
+}
+}  // namespace implementation
+}  // namespace V1_1
+}  // namespace wifi
+}  // namespace supplicant
+}  // namespace hardware
+}  // namespace android
diff --git a/wpa_supplicant/hidl/1.1/p2p_network.h b/wpa_supplicant/hidl/1.1/p2p_network.h
new file mode 100644
index 0000000..3c36f6d
--- /dev/null
+++ b/wpa_supplicant/hidl/1.1/p2p_network.h
@@ -0,0 +1,103 @@
+/*
+ * hidl interface for wpa_supplicant daemon
+ * Copyright (c) 2004-2016, Jouni Malinen <j@w1.fi>
+ * Copyright (c) 2004-2016, Roshan Pius <rpius@google.com>
+ *
+ * This software may be distributed under the terms of the BSD license.
+ * See README for more details.
+ */
+
+#ifndef WPA_SUPPLICANT_HIDL_P2P_NETWORK_H
+#define WPA_SUPPLICANT_HIDL_P2P_NETWORK_H
+
+#include <android-base/macros.h>
+
+#include <android/hardware/wifi/supplicant/1.0/ISupplicantP2pNetwork.h>
+#include <android/hardware/wifi/supplicant/1.0/ISupplicantP2pNetworkCallback.h>
+
+extern "C" {
+#include "utils/common.h"
+#include "utils/includes.h"
+#include "wpa_supplicant_i.h"
+}
+
+namespace android {
+namespace hardware {
+namespace wifi {
+namespace supplicant {
+namespace V1_1 {
+namespace implementation {
+using namespace android::hardware::wifi::supplicant::V1_0;
+
+/**
+ * Implementation of P2pNetwork hidl object. Each unique hidl
+ * object is used for control operations on a specific network
+ * controlled by wpa_supplicant.
+ */
+class P2pNetwork : public ISupplicantP2pNetwork
+{
+public:
+	P2pNetwork(
+	    struct wpa_global* wpa_global, const char ifname[], int network_id);
+	~P2pNetwork() override = default;
+	// Refer to |StaIface::invalidate()|.
+	void invalidate();
+	bool isValid();
+
+	// Hidl methods exposed.
+	Return<void> getId(getId_cb _hidl_cb) override;
+	Return<void> getInterfaceName(getInterfaceName_cb _hidl_cb) override;
+	Return<void> getType(getType_cb _hidl_cb) override;
+	Return<void> registerCallback(
+	    const sp<ISupplicantP2pNetworkCallback>& callback,
+	    registerCallback_cb _hidl_cb) override;
+	Return<void> getSsid(getSsid_cb _hidl_cb) override;
+	Return<void> getBssid(getBssid_cb _hidl_cb) override;
+	Return<void> isCurrent(isCurrent_cb _hidl_cb) override;
+	Return<void> isPersistent(isPersistent_cb _hidl_cb) override;
+	Return<void> isGo(isGo_cb _hidl_cb) override;
+	Return<void> setClientList(
+	    const hidl_vec<hidl_array<uint8_t, 6>>& clients,
+	    setClientList_cb _hidl_cb) override;
+	Return<void> getClientList(getClientList_cb _hidl_cb) override;
+
+private:
+	// Corresponding worker functions for the HIDL methods.
+	std::pair<SupplicantStatus, uint32_t> getIdInternal();
+	std::pair<SupplicantStatus, std::string> getInterfaceNameInternal();
+	std::pair<SupplicantStatus, IfaceType> getTypeInternal();
+	SupplicantStatus registerCallbackInternal(
+	    const sp<ISupplicantP2pNetworkCallback>& callback);
+	std::pair<SupplicantStatus, std::vector<uint8_t>> getSsidInternal();
+	std::pair<SupplicantStatus, std::array<uint8_t, 6>> getBssidInternal();
+	std::pair<SupplicantStatus, bool> isCurrentInternal();
+	std::pair<SupplicantStatus, bool> isPersistentInternal();
+	std::pair<SupplicantStatus, bool> isGoInternal();
+	SupplicantStatus setClientListInternal(
+	    const std::vector<hidl_array<uint8_t, 6>>& clients);
+	std::pair<SupplicantStatus, std::vector<hidl_array<uint8_t, 6>>>
+	getClientListInternal();
+
+	struct wpa_ssid* retrieveNetworkPtr();
+	struct wpa_supplicant* retrieveIfacePtr();
+
+	// Reference to the global wpa_struct. This is assumed to be valid
+	// for the lifetime of the process.
+	const struct wpa_global* wpa_global_;
+	// Name of the iface this network belongs to.
+	const std::string ifname_;
+	// Id of the network this hidl object controls.
+	const int network_id_;
+	bool is_valid_;
+
+	DISALLOW_COPY_AND_ASSIGN(P2pNetwork);
+};
+
+}  // namespace implementation
+}  // namespace V1_1
+}  // namespace wifi
+}  // namespace supplicant
+}  // namespace hardware
+}  // namespace android
+
+#endif  // WPA_SUPPLICANT_HIDL_P2P_NETWORK_H
diff --git a/wpa_supplicant/hidl/1.1/sta_iface.cpp b/wpa_supplicant/hidl/1.1/sta_iface.cpp
new file mode 100644
index 0000000..6436745
--- /dev/null
+++ b/wpa_supplicant/hidl/1.1/sta_iface.cpp
@@ -0,0 +1,1034 @@
+/*
+ * hidl interface for wpa_supplicant daemon
+ * Copyright (c) 2004-2016, Jouni Malinen <j@w1.fi>
+ * Copyright (c) 2004-2016, Roshan Pius <rpius@google.com>
+ *
+ * This software may be distributed under the terms of the BSD license.
+ * See README for more details.
+ */
+
+#include "hidl_manager.h"
+#include "hidl_return_util.h"
+#include "iface_config_utils.h"
+#include "misc_utils.h"
+#include "sta_iface.h"
+
+extern "C" {
+#include "utils/eloop.h"
+#include "gas_query.h"
+#include "interworking.h"
+#include "hs20_supplicant.h"
+#include "wps_supplicant.h"
+}
+
+namespace {
+using android::hardware::wifi::supplicant::V1_1::ISupplicantStaIface;
+using android::hardware::wifi::supplicant::V1_0::SupplicantStatus;
+using android::hardware::wifi::supplicant::V1_0::SupplicantStatusCode;
+using android::hardware::wifi::supplicant::V1_1::implementation::HidlManager;
+
+constexpr uint32_t kMaxAnqpElems = 100;
+constexpr char kGetMacAddress[] = "MACADDR";
+constexpr char kStartRxFilter[] = "RXFILTER-START";
+constexpr char kStopRxFilter[] = "RXFILTER-STOP";
+constexpr char kAddRxFilter[] = "RXFILTER-ADD";
+constexpr char kRemoveRxFilter[] = "RXFILTER-REMOVE";
+constexpr char kSetBtCoexistenceMode[] = "BTCOEXMODE";
+constexpr char kSetBtCoexistenceScanStart[] = "BTCOEXSCAN-START";
+constexpr char kSetBtCoexistenceScanStop[] = "BTCOEXSCAN-STOP";
+constexpr char kSetSupendModeEnabled[] = "SETSUSPENDMODE 1";
+constexpr char kSetSupendModeDisabled[] = "SETSUSPENDMODE 0";
+constexpr char kSetCountryCode[] = "COUNTRY";
+constexpr uint32_t kExtRadioWorkDefaultTimeoutInSec = static_cast<uint32_t>(
+    ISupplicantStaIface::ExtRadioWorkDefaults::TIMEOUT_IN_SECS);
+constexpr char kExtRadioWorkNamePrefix[] = "ext:";
+
+uint8_t convertHidlRxFilterTypeToInternal(
+    ISupplicantStaIface::RxFilterType type)
+{
+	switch (type) {
+	case ISupplicantStaIface::RxFilterType::V4_MULTICAST:
+		return 2;
+	case ISupplicantStaIface::RxFilterType::V6_MULTICAST:
+		return 3;
+	};
+	WPA_ASSERT(false);
+}
+
+uint8_t convertHidlBtCoexModeToInternal(
+    ISupplicantStaIface::BtCoexistenceMode mode)
+{
+	switch (mode) {
+	case ISupplicantStaIface::BtCoexistenceMode::ENABLED:
+		return 0;
+	case ISupplicantStaIface::BtCoexistenceMode::DISABLED:
+		return 1;
+	case ISupplicantStaIface::BtCoexistenceMode::SENSE:
+		return 2;
+	};
+	WPA_ASSERT(false);
+}
+
+SupplicantStatus doZeroArgDriverCommand(
+    struct wpa_supplicant *wpa_s, const char *cmd)
+{
+	std::vector<char> cmd_vec(cmd, cmd + strlen(cmd) + 1);
+	char driver_cmd_reply_buf[4096] = {};
+	if (wpa_drv_driver_cmd(
+		wpa_s, cmd_vec.data(), driver_cmd_reply_buf,
+		sizeof(driver_cmd_reply_buf))) {
+		return {SupplicantStatusCode::FAILURE_UNKNOWN, ""};
+	}
+	return {SupplicantStatusCode::SUCCESS, ""};
+}
+
+SupplicantStatus doOneArgDriverCommand(
+    struct wpa_supplicant *wpa_s, const char *cmd, uint8_t arg)
+{
+	std::string cmd_str = std::string(cmd) + " " + std::to_string(arg);
+	return doZeroArgDriverCommand(wpa_s, cmd_str.c_str());
+}
+
+SupplicantStatus doOneArgDriverCommand(
+    struct wpa_supplicant *wpa_s, const char *cmd, const std::string &arg)
+{
+	std::string cmd_str = std::string(cmd) + " " + arg;
+	return doZeroArgDriverCommand(wpa_s, cmd_str.c_str());
+}
+
+void endExtRadioWork(struct wpa_radio_work *work)
+{
+	auto *ework = static_cast<struct wpa_external_work *>(work->ctx);
+	work->wpa_s->ext_work_in_progress = 0;
+	radio_work_done(work);
+	os_free(ework);
+}
+
+void extRadioWorkTimeoutCb(void *eloop_ctx, void *timeout_ctx)
+{
+	auto *work = static_cast<struct wpa_radio_work *>(eloop_ctx);
+	auto *ework = static_cast<struct wpa_external_work *>(work->ctx);
+	wpa_dbg(
+	    work->wpa_s, MSG_DEBUG, "Timing out external radio work %u (%s)",
+	    ework->id, work->type);
+
+	HidlManager *hidl_manager = HidlManager::getInstance();
+	WPA_ASSERT(hidl_manager);
+	hidl_manager->notifyExtRadioWorkTimeout(work->wpa_s, ework->id);
+
+	endExtRadioWork(work);
+}
+
+void startExtRadioWork(struct wpa_radio_work *work)
+{
+	auto *ework = static_cast<struct wpa_external_work *>(work->ctx);
+	work->wpa_s->ext_work_in_progress = 1;
+	if (!ework->timeout) {
+		ework->timeout = kExtRadioWorkDefaultTimeoutInSec;
+	}
+	eloop_register_timeout(
+	    ework->timeout, 0, extRadioWorkTimeoutCb, work, nullptr);
+}
+
+void extRadioWorkStartCb(struct wpa_radio_work *work, int deinit)
+{
+	// deinit==1 is invoked during interface removal. Since the HIDL
+	// interface does not support interface addition/removal, we don't
+	// need to handle this scenario.
+	WPA_ASSERT(!deinit);
+
+	auto *ework = static_cast<struct wpa_external_work *>(work->ctx);
+	wpa_dbg(
+	    work->wpa_s, MSG_DEBUG, "Starting external radio work %u (%s)",
+	    ework->id, ework->type);
+
+	HidlManager *hidl_manager = HidlManager::getInstance();
+	WPA_ASSERT(hidl_manager);
+	hidl_manager->notifyExtRadioWorkStart(work->wpa_s, ework->id);
+
+	startExtRadioWork(work);
+}
+
+}  // namespace
+
+namespace android {
+namespace hardware {
+namespace wifi {
+namespace supplicant {
+namespace V1_1 {
+namespace implementation {
+using hidl_return_util::validateAndCall;
+
+using namespace android::hardware::wifi::supplicant::V1_0;
+using namespace android::hardware::wifi::supplicant::V1_1;
+using V1_0::ISupplicantStaIfaceCallback;
+
+StaIface::StaIface(struct wpa_global *wpa_global, const char ifname[])
+    : wpa_global_(wpa_global), ifname_(ifname), is_valid_(true)
+{
+}
+
+void StaIface::invalidate() { is_valid_ = false; }
+bool StaIface::isValid()
+{
+	return (is_valid_ && (retrieveIfacePtr() != nullptr));
+}
+
+Return<void> StaIface::getName(getName_cb _hidl_cb)
+{
+	return validateAndCall(
+	    this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
+	    &StaIface::getNameInternal, _hidl_cb);
+}
+
+Return<void> StaIface::getType(getType_cb _hidl_cb)
+{
+	return validateAndCall(
+	    this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
+	    &StaIface::getTypeInternal, _hidl_cb);
+}
+
+Return<void> StaIface::addNetwork(addNetwork_cb _hidl_cb)
+{
+	return validateAndCall(
+	    this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
+	    &StaIface::addNetworkInternal, _hidl_cb);
+}
+
+Return<void> StaIface::removeNetwork(
+    SupplicantNetworkId id, removeNetwork_cb _hidl_cb)
+{
+	return validateAndCall(
+	    this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
+	    &StaIface::removeNetworkInternal, _hidl_cb, id);
+}
+
+Return<void> StaIface::getNetwork(
+    SupplicantNetworkId id, getNetwork_cb _hidl_cb)
+{
+	return validateAndCall(
+	    this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
+	    &StaIface::getNetworkInternal, _hidl_cb, id);
+}
+
+Return<void> StaIface::listNetworks(listNetworks_cb _hidl_cb)
+{
+	return validateAndCall(
+	    this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
+	    &StaIface::listNetworksInternal, _hidl_cb);
+}
+
+Return<void> StaIface::registerCallback(
+    const sp<ISupplicantStaIfaceCallback>
+    & callback, registerCallback_cb _hidl_cb)
+{
+	return validateAndCall(
+	    this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
+	    &StaIface::registerCallbackInternal, _hidl_cb, callback);
+}
+
+Return<void> StaIface::registerCallback_1_1(
+    const sp<V1_1::ISupplicantStaIfaceCallback> &callback,
+    registerCallback_cb _hidl_cb)
+{
+	sp<V1_0::ISupplicantStaIfaceCallback> callback_1_0 =  callback;
+	return validateAndCall(
+	    this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
+	    &StaIface::registerCallbackInternal, _hidl_cb, callback_1_0);
+}
+
+Return<void> StaIface::reassociate(reassociate_cb _hidl_cb)
+{
+	return validateAndCall(
+	    this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
+	    &StaIface::reassociateInternal, _hidl_cb);
+}
+
+Return<void> StaIface::reconnect(reconnect_cb _hidl_cb)
+{
+	return validateAndCall(
+	    this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
+	    &StaIface::reconnectInternal, _hidl_cb);
+}
+
+Return<void> StaIface::disconnect(disconnect_cb _hidl_cb)
+{
+	return validateAndCall(
+	    this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
+	    &StaIface::disconnectInternal, _hidl_cb);
+}
+
+Return<void> StaIface::setPowerSave(bool enable, setPowerSave_cb _hidl_cb)
+{
+	return validateAndCall(
+	    this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
+	    &StaIface::setPowerSaveInternal, _hidl_cb, enable);
+}
+
+Return<void> StaIface::initiateTdlsDiscover(
+    const hidl_array<uint8_t, 6> &mac_address, initiateTdlsDiscover_cb _hidl_cb)
+{
+	return validateAndCall(
+	    this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
+	    &StaIface::initiateTdlsDiscoverInternal, _hidl_cb, mac_address);
+}
+
+Return<void> StaIface::initiateTdlsSetup(
+    const hidl_array<uint8_t, 6> &mac_address, initiateTdlsSetup_cb _hidl_cb)
+{
+	return validateAndCall(
+	    this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
+	    &StaIface::initiateTdlsSetupInternal, _hidl_cb, mac_address);
+}
+
+Return<void> StaIface::initiateTdlsTeardown(
+    const hidl_array<uint8_t, 6> &mac_address, initiateTdlsTeardown_cb _hidl_cb)
+{
+	return validateAndCall(
+	    this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
+	    &StaIface::initiateTdlsTeardownInternal, _hidl_cb, mac_address);
+}
+Return<void> StaIface::initiateAnqpQuery(
+    const hidl_array<uint8_t, 6> &mac_address,
+    const hidl_vec<ISupplicantStaIface::AnqpInfoId> &info_elements,
+    const hidl_vec<ISupplicantStaIface::Hs20AnqpSubtypes> &sub_types,
+    initiateAnqpQuery_cb _hidl_cb)
+{
+	return validateAndCall(
+	    this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
+	    &StaIface::initiateAnqpQueryInternal, _hidl_cb, mac_address,
+	    info_elements, sub_types);
+}
+
+Return<void> StaIface::initiateHs20IconQuery(
+    const hidl_array<uint8_t, 6> &mac_address, const hidl_string &file_name,
+    initiateHs20IconQuery_cb _hidl_cb)
+{
+	return validateAndCall(
+	    this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
+	    &StaIface::initiateHs20IconQueryInternal, _hidl_cb, mac_address,
+	    file_name);
+}
+
+Return<void> StaIface::getMacAddress(getMacAddress_cb _hidl_cb)
+{
+	return validateAndCall(
+	    this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
+	    &StaIface::getMacAddressInternal, _hidl_cb);
+}
+
+Return<void> StaIface::startRxFilter(startRxFilter_cb _hidl_cb)
+{
+	return validateAndCall(
+	    this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
+	    &StaIface::startRxFilterInternal, _hidl_cb);
+}
+
+Return<void> StaIface::stopRxFilter(stopRxFilter_cb _hidl_cb)
+{
+	return validateAndCall(
+	    this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
+	    &StaIface::stopRxFilterInternal, _hidl_cb);
+}
+
+Return<void> StaIface::addRxFilter(
+    ISupplicantStaIface::RxFilterType type, addRxFilter_cb _hidl_cb)
+{
+	return validateAndCall(
+	    this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
+	    &StaIface::addRxFilterInternal, _hidl_cb, type);
+}
+
+Return<void> StaIface::removeRxFilter(
+    ISupplicantStaIface::RxFilterType type, removeRxFilter_cb _hidl_cb)
+{
+	return validateAndCall(
+	    this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
+	    &StaIface::removeRxFilterInternal, _hidl_cb, type);
+}
+
+Return<void> StaIface::setBtCoexistenceMode(
+    ISupplicantStaIface::BtCoexistenceMode mode,
+    setBtCoexistenceMode_cb _hidl_cb)
+{
+	return validateAndCall(
+	    this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
+	    &StaIface::setBtCoexistenceModeInternal, _hidl_cb, mode);
+}
+
+Return<void> StaIface::setBtCoexistenceScanModeEnabled(
+    bool enable, setBtCoexistenceScanModeEnabled_cb _hidl_cb)
+{
+	return validateAndCall(
+	    this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
+	    &StaIface::setBtCoexistenceScanModeEnabledInternal, _hidl_cb,
+	    enable);
+}
+
+Return<void> StaIface::setSuspendModeEnabled(
+    bool enable, setSuspendModeEnabled_cb _hidl_cb)
+{
+	return validateAndCall(
+	    this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
+	    &StaIface::setSuspendModeEnabledInternal, _hidl_cb, enable);
+}
+
+Return<void> StaIface::setCountryCode(
+    const hidl_array<int8_t, 2> &code, setCountryCode_cb _hidl_cb)
+{
+	return validateAndCall(
+	    this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
+	    &StaIface::setCountryCodeInternal, _hidl_cb, code);
+}
+
+Return<void> StaIface::startWpsRegistrar(
+    const hidl_array<uint8_t, 6> &bssid, const hidl_string &pin,
+    startWpsRegistrar_cb _hidl_cb)
+{
+	return validateAndCall(
+	    this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
+	    &StaIface::startWpsRegistrarInternal, _hidl_cb, bssid, pin);
+}
+
+Return<void> StaIface::startWpsPbc(
+    const hidl_array<uint8_t, 6> &bssid, startWpsPbc_cb _hidl_cb)
+{
+	return validateAndCall(
+	    this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
+	    &StaIface::startWpsPbcInternal, _hidl_cb, bssid);
+}
+
+Return<void> StaIface::startWpsPinKeypad(
+    const hidl_string &pin, startWpsPinKeypad_cb _hidl_cb)
+{
+	return validateAndCall(
+	    this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
+	    &StaIface::startWpsPinKeypadInternal, _hidl_cb, pin);
+}
+
+Return<void> StaIface::startWpsPinDisplay(
+    const hidl_array<uint8_t, 6> &bssid, startWpsPinDisplay_cb _hidl_cb)
+{
+	return validateAndCall(
+	    this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
+	    &StaIface::startWpsPinDisplayInternal, _hidl_cb, bssid);
+}
+
+Return<void> StaIface::cancelWps(cancelWps_cb _hidl_cb)
+{
+	return validateAndCall(
+	    this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
+	    &StaIface::cancelWpsInternal, _hidl_cb);
+}
+
+Return<void> StaIface::setWpsDeviceName(
+    const hidl_string &name, setWpsDeviceName_cb _hidl_cb)
+{
+	return validateAndCall(
+	    this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
+	    &StaIface::setWpsDeviceNameInternal, _hidl_cb, name);
+}
+
+Return<void> StaIface::setWpsDeviceType(
+    const hidl_array<uint8_t, 8> &type, setWpsDeviceType_cb _hidl_cb)
+{
+	return validateAndCall(
+	    this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
+	    &StaIface::setWpsDeviceTypeInternal, _hidl_cb, type);
+}
+
+Return<void> StaIface::setWpsManufacturer(
+    const hidl_string &manufacturer, setWpsManufacturer_cb _hidl_cb)
+{
+	return validateAndCall(
+	    this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
+	    &StaIface::setWpsManufacturerInternal, _hidl_cb, manufacturer);
+}
+
+Return<void> StaIface::setWpsModelName(
+    const hidl_string &model_name, setWpsModelName_cb _hidl_cb)
+{
+	return validateAndCall(
+	    this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
+	    &StaIface::setWpsModelNameInternal, _hidl_cb, model_name);
+}
+
+Return<void> StaIface::setWpsModelNumber(
+    const hidl_string &model_number, setWpsModelNumber_cb _hidl_cb)
+{
+	return validateAndCall(
+	    this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
+	    &StaIface::setWpsModelNumberInternal, _hidl_cb, model_number);
+}
+
+Return<void> StaIface::setWpsSerialNumber(
+    const hidl_string &serial_number, setWpsSerialNumber_cb _hidl_cb)
+{
+	return validateAndCall(
+	    this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
+	    &StaIface::setWpsSerialNumberInternal, _hidl_cb, serial_number);
+}
+
+Return<void> StaIface::setWpsConfigMethods(
+    uint16_t config_methods, setWpsConfigMethods_cb _hidl_cb)
+{
+	return validateAndCall(
+	    this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
+	    &StaIface::setWpsConfigMethodsInternal, _hidl_cb, config_methods);
+}
+
+Return<void> StaIface::setExternalSim(
+    bool useExternalSim, setExternalSim_cb _hidl_cb)
+{
+	return validateAndCall(
+	    this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
+	    &StaIface::setExternalSimInternal, _hidl_cb, useExternalSim);
+}
+
+Return<void> StaIface::addExtRadioWork(
+    const hidl_string &name, uint32_t freq_in_mhz, uint32_t timeout_in_sec,
+    addExtRadioWork_cb _hidl_cb)
+{
+	return validateAndCall(
+	    this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
+	    &StaIface::addExtRadioWorkInternal, _hidl_cb, name, freq_in_mhz,
+	    timeout_in_sec);
+}
+
+Return<void> StaIface::removeExtRadioWork(
+    uint32_t id, removeExtRadioWork_cb _hidl_cb)
+{
+	return validateAndCall(
+	    this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
+	    &StaIface::removeExtRadioWorkInternal, _hidl_cb, id);
+}
+
+Return<void> StaIface::enableAutoReconnect(
+    bool enable, enableAutoReconnect_cb _hidl_cb)
+{
+	return validateAndCall(
+	    this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
+	    &StaIface::enableAutoReconnectInternal, _hidl_cb, enable);
+}
+
+std::pair<SupplicantStatus, std::string> StaIface::getNameInternal()
+{
+	return {{SupplicantStatusCode::SUCCESS, ""}, ifname_};
+}
+
+std::pair<SupplicantStatus, IfaceType> StaIface::getTypeInternal()
+{
+	return {{SupplicantStatusCode::SUCCESS, ""}, IfaceType::STA};
+}
+
+std::pair<SupplicantStatus, sp<ISupplicantNetwork>>
+StaIface::addNetworkInternal()
+{
+	android::sp<ISupplicantStaNetwork> network;
+	struct wpa_supplicant *wpa_s = retrieveIfacePtr();
+	struct wpa_ssid *ssid = wpa_supplicant_add_network(wpa_s);
+	if (!ssid) {
+		return {{SupplicantStatusCode::FAILURE_UNKNOWN, ""}, network};
+	}
+	HidlManager *hidl_manager = HidlManager::getInstance();
+	if (!hidl_manager ||
+	    hidl_manager->getStaNetworkHidlObjectByIfnameAndNetworkId(
+		wpa_s->ifname, ssid->id, &network)) {
+		return {{SupplicantStatusCode::FAILURE_UNKNOWN, ""}, network};
+	}
+	return {{SupplicantStatusCode::SUCCESS, ""}, network};
+}
+
+SupplicantStatus StaIface::removeNetworkInternal(SupplicantNetworkId id)
+{
+	struct wpa_supplicant *wpa_s = retrieveIfacePtr();
+	int result = wpa_supplicant_remove_network(wpa_s, id);
+	if (result == -1) {
+		return {SupplicantStatusCode::FAILURE_NETWORK_UNKNOWN, ""};
+	}
+	if (result != 0) {
+		return {SupplicantStatusCode::FAILURE_UNKNOWN, ""};
+	}
+	return {SupplicantStatusCode::SUCCESS, ""};
+}
+
+std::pair<SupplicantStatus, sp<ISupplicantNetwork>>
+StaIface::getNetworkInternal(SupplicantNetworkId id)
+{
+	android::sp<ISupplicantStaNetwork> network;
+	struct wpa_supplicant *wpa_s = retrieveIfacePtr();
+	struct wpa_ssid *ssid = wpa_config_get_network(wpa_s->conf, id);
+	if (!ssid) {
+		return {{SupplicantStatusCode::FAILURE_NETWORK_UNKNOWN, ""},
+			network};
+	}
+	HidlManager *hidl_manager = HidlManager::getInstance();
+	if (!hidl_manager ||
+	    hidl_manager->getStaNetworkHidlObjectByIfnameAndNetworkId(
+		wpa_s->ifname, ssid->id, &network)) {
+		return {{SupplicantStatusCode::FAILURE_UNKNOWN, ""}, network};
+	}
+	return {{SupplicantStatusCode::SUCCESS, ""}, network};
+}
+
+std::pair<SupplicantStatus, std::vector<SupplicantNetworkId>>
+StaIface::listNetworksInternal()
+{
+	std::vector<SupplicantNetworkId> network_ids;
+	struct wpa_supplicant *wpa_s = retrieveIfacePtr();
+	for (struct wpa_ssid *wpa_ssid = wpa_s->conf->ssid; wpa_ssid;
+	     wpa_ssid = wpa_ssid->next) {
+		network_ids.emplace_back(wpa_ssid->id);
+	}
+	return {{SupplicantStatusCode::SUCCESS, ""}, std::move(network_ids)};
+}
+
+SupplicantStatus StaIface::registerCallbackInternal(
+    const sp<ISupplicantStaIfaceCallback> &callback)
+{
+	HidlManager *hidl_manager = HidlManager::getInstance();
+	if (!hidl_manager ||
+	    hidl_manager->addStaIfaceCallbackHidlObject(ifname_, callback)) {
+		return {SupplicantStatusCode::FAILURE_UNKNOWN, ""};
+	}
+	return {SupplicantStatusCode::SUCCESS, ""};
+}
+
+SupplicantStatus StaIface::reassociateInternal()
+{
+	struct wpa_supplicant *wpa_s = retrieveIfacePtr();
+	if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED) {
+		return {SupplicantStatusCode::FAILURE_IFACE_DISABLED, ""};
+	}
+	wpas_request_connection(wpa_s);
+	return {SupplicantStatusCode::SUCCESS, ""};
+}
+
+SupplicantStatus StaIface::reconnectInternal()
+{
+	struct wpa_supplicant *wpa_s = retrieveIfacePtr();
+	if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED) {
+		return {SupplicantStatusCode::FAILURE_IFACE_DISABLED, ""};
+	}
+	if (!wpa_s->disconnected) {
+		return {SupplicantStatusCode::FAILURE_IFACE_NOT_DISCONNECTED,
+			""};
+	}
+	wpas_request_connection(wpa_s);
+	return {SupplicantStatusCode::SUCCESS, ""};
+}
+
+SupplicantStatus StaIface::disconnectInternal()
+{
+	struct wpa_supplicant *wpa_s = retrieveIfacePtr();
+	if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED) {
+		return {SupplicantStatusCode::FAILURE_IFACE_DISABLED, ""};
+	}
+	wpas_request_disconnection(wpa_s);
+	return {SupplicantStatusCode::SUCCESS, ""};
+}
+
+SupplicantStatus StaIface::setPowerSaveInternal(bool enable)
+{
+	struct wpa_supplicant *wpa_s = retrieveIfacePtr();
+	if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED) {
+		return {SupplicantStatusCode::FAILURE_IFACE_DISABLED, ""};
+	}
+	if (wpa_drv_set_p2p_powersave(wpa_s, enable, -1, -1)) {
+		return {SupplicantStatusCode::FAILURE_UNKNOWN, ""};
+	}
+	return {SupplicantStatusCode::SUCCESS, ""};
+}
+
+SupplicantStatus StaIface::initiateTdlsDiscoverInternal(
+    const std::array<uint8_t, 6> &mac_address)
+{
+	struct wpa_supplicant *wpa_s = retrieveIfacePtr();
+	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) {
+		wpa_printf(MSG_INFO, "StaIface: TDLS discover failed: %d", ret);
+	}
+	return {SupplicantStatusCode::SUCCESS, ""};
+}
+
+SupplicantStatus StaIface::initiateTdlsSetupInternal(
+    const std::array<uint8_t, 6> &mac_address)
+{
+	struct wpa_supplicant *wpa_s = retrieveIfacePtr();
+	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) {
+		wpa_printf(MSG_INFO, "StaIface: TDLS setup failed: %d", ret);
+	}
+	return {SupplicantStatusCode::SUCCESS, ""};
+}
+
+SupplicantStatus StaIface::initiateTdlsTeardownInternal(
+    const std::array<uint8_t, 6> &mac_address)
+{
+	struct wpa_supplicant *wpa_s = retrieveIfacePtr();
+	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) {
+		wpa_printf(MSG_INFO, "StaIface: TDLS teardown failed: %d", ret);
+	}
+	return {SupplicantStatusCode::SUCCESS, ""};
+}
+
+SupplicantStatus StaIface::initiateAnqpQueryInternal(
+    const std::array<uint8_t, 6> &mac_address,
+    const std::vector<ISupplicantStaIface::AnqpInfoId> &info_elements,
+    const std::vector<ISupplicantStaIface::Hs20AnqpSubtypes> &sub_types)
+{
+	struct wpa_supplicant *wpa_s = retrieveIfacePtr();
+	if (info_elements.size() > kMaxAnqpElems) {
+		return {SupplicantStatusCode::FAILURE_ARGS_INVALID, ""};
+	}
+	uint16_t info_elems_buf[kMaxAnqpElems];
+	uint32_t num_info_elems = 0;
+	for (const auto &info_element : info_elements) {
+		info_elems_buf[num_info_elems++] =
+		    static_cast<std::underlying_type<
+			ISupplicantStaIface::AnqpInfoId>::type>(info_element);
+	}
+	uint32_t sub_types_bitmask = 0;
+	for (const auto &type : sub_types) {
+		sub_types_bitmask |= BIT(
+		    static_cast<std::underlying_type<
+			ISupplicantStaIface::Hs20AnqpSubtypes>::type>(type));
+	}
+	if (anqp_send_req(
+		wpa_s, mac_address.data(), info_elems_buf, num_info_elems,
+		sub_types_bitmask, false)) {
+		return {SupplicantStatusCode::FAILURE_UNKNOWN, ""};
+	}
+	return {SupplicantStatusCode::SUCCESS, ""};
+}
+
+SupplicantStatus StaIface::initiateHs20IconQueryInternal(
+    const std::array<uint8_t, 6> &mac_address, const std::string &file_name)
+{
+	struct wpa_supplicant *wpa_s = retrieveIfacePtr();
+	wpa_s->fetch_osu_icon_in_progress = 0;
+	if (hs20_anqp_send_req(
+		wpa_s, mac_address.data(), BIT(HS20_STYPE_ICON_REQUEST),
+		reinterpret_cast<const uint8_t *>(file_name.c_str()),
+		file_name.size(), true)) {
+		return {SupplicantStatusCode::FAILURE_UNKNOWN, ""};
+	}
+	return {SupplicantStatusCode::SUCCESS, ""};
+}
+
+std::pair<SupplicantStatus, std::array<uint8_t, 6>>
+StaIface::getMacAddressInternal()
+{
+	struct wpa_supplicant *wpa_s = retrieveIfacePtr();
+	std::vector<char> cmd(
+	    kGetMacAddress, kGetMacAddress + sizeof(kGetMacAddress));
+	char driver_cmd_reply_buf[4096] = {};
+	int ret = wpa_drv_driver_cmd(
+	    wpa_s, cmd.data(), driver_cmd_reply_buf,
+	    sizeof(driver_cmd_reply_buf));
+	// Reply is of the format: "Macaddr = XX:XX:XX:XX:XX:XX"
+	std::string reply_str = driver_cmd_reply_buf;
+	if (ret < 0 || reply_str.empty() ||
+	    reply_str.find("=") == std::string::npos) {
+		return {{SupplicantStatusCode::FAILURE_UNKNOWN, ""}, {}};
+	}
+	// Remove all whitespace first and then split using the delimiter "=".
+	reply_str.erase(
+	    remove_if(reply_str.begin(), reply_str.end(), isspace),
+	    reply_str.end());
+	std::string mac_addr_str =
+	    reply_str.substr(reply_str.find("=") + 1, reply_str.size());
+	std::array<uint8_t, 6> mac_addr;
+	if (hwaddr_aton(mac_addr_str.c_str(), mac_addr.data())) {
+		return {{SupplicantStatusCode::FAILURE_UNKNOWN, ""}, {}};
+	}
+	return {{SupplicantStatusCode::SUCCESS, ""}, mac_addr};
+}
+
+SupplicantStatus StaIface::startRxFilterInternal()
+{
+	return doZeroArgDriverCommand(retrieveIfacePtr(), kStartRxFilter);
+}
+
+SupplicantStatus StaIface::stopRxFilterInternal()
+{
+	return doZeroArgDriverCommand(retrieveIfacePtr(), kStopRxFilter);
+}
+
+SupplicantStatus StaIface::addRxFilterInternal(
+    ISupplicantStaIface::RxFilterType type)
+{
+	return doOneArgDriverCommand(
+	    retrieveIfacePtr(), kAddRxFilter,
+	    convertHidlRxFilterTypeToInternal(type));
+}
+
+SupplicantStatus StaIface::removeRxFilterInternal(
+    ISupplicantStaIface::RxFilterType type)
+{
+	return doOneArgDriverCommand(
+	    retrieveIfacePtr(), kRemoveRxFilter,
+	    convertHidlRxFilterTypeToInternal(type));
+}
+
+SupplicantStatus StaIface::setBtCoexistenceModeInternal(
+    ISupplicantStaIface::BtCoexistenceMode mode)
+{
+	return doOneArgDriverCommand(
+	    retrieveIfacePtr(), kSetBtCoexistenceMode,
+	    convertHidlBtCoexModeToInternal(mode));
+}
+
+SupplicantStatus StaIface::setBtCoexistenceScanModeEnabledInternal(bool enable)
+{
+	const char *cmd;
+	if (enable) {
+		cmd = kSetBtCoexistenceScanStart;
+	} else {
+		cmd = kSetBtCoexistenceScanStop;
+	}
+	return doZeroArgDriverCommand(retrieveIfacePtr(), cmd);
+}
+
+SupplicantStatus StaIface::setSuspendModeEnabledInternal(bool enable)
+{
+	const char *cmd;
+	if (enable) {
+		cmd = kSetSupendModeEnabled;
+	} else {
+		cmd = kSetSupendModeDisabled;
+	}
+	return doZeroArgDriverCommand(retrieveIfacePtr(), cmd);
+}
+
+SupplicantStatus StaIface::setCountryCodeInternal(
+    const std::array<int8_t, 2> &code)
+{
+	struct wpa_supplicant *wpa_s = retrieveIfacePtr();
+	SupplicantStatus status = doOneArgDriverCommand(
+	    wpa_s, kSetCountryCode,
+	    std::string(std::begin(code), std::end(code)));
+	if (status.code != SupplicantStatusCode::SUCCESS) {
+		return status;
+	}
+	struct p2p_data *p2p = wpa_s->global->p2p;
+	if (p2p) {
+		char country[3];
+		country[0] = code[0];
+		country[1] = code[1];
+		country[2] = 0x04;
+		p2p_set_country(p2p, country);
+	}
+	return {SupplicantStatusCode::SUCCESS, ""};
+}
+
+SupplicantStatus StaIface::startWpsRegistrarInternal(
+    const std::array<uint8_t, 6> &bssid, const std::string &pin)
+{
+	struct wpa_supplicant *wpa_s = retrieveIfacePtr();
+	if (wpas_wps_start_reg(wpa_s, bssid.data(), pin.c_str(), nullptr)) {
+		return {SupplicantStatusCode::FAILURE_UNKNOWN, ""};
+	}
+	return {SupplicantStatusCode::SUCCESS, ""};
+}
+
+SupplicantStatus StaIface::startWpsPbcInternal(
+    const std::array<uint8_t, 6> &bssid)
+{
+	struct wpa_supplicant *wpa_s = retrieveIfacePtr();
+	const uint8_t *bssid_addr =
+	    is_zero_ether_addr(bssid.data()) ? nullptr : bssid.data();
+	if (wpas_wps_start_pbc(wpa_s, bssid_addr, 0)) {
+		return {SupplicantStatusCode::FAILURE_UNKNOWN, ""};
+	}
+	return {SupplicantStatusCode::SUCCESS, ""};
+}
+
+SupplicantStatus StaIface::startWpsPinKeypadInternal(const std::string &pin)
+{
+	struct wpa_supplicant *wpa_s = retrieveIfacePtr();
+	if (wpas_wps_start_pin(
+		wpa_s, nullptr, pin.c_str(), 0, DEV_PW_DEFAULT)) {
+		return {SupplicantStatusCode::FAILURE_UNKNOWN, ""};
+	}
+	return {SupplicantStatusCode::SUCCESS, ""};
+}
+
+std::pair<SupplicantStatus, std::string> StaIface::startWpsPinDisplayInternal(
+    const std::array<uint8_t, 6> &bssid)
+{
+	struct wpa_supplicant *wpa_s = retrieveIfacePtr();
+	const uint8_t *bssid_addr =
+	    is_zero_ether_addr(bssid.data()) ? nullptr : bssid.data();
+	int pin =
+	    wpas_wps_start_pin(wpa_s, bssid_addr, nullptr, 0, DEV_PW_DEFAULT);
+	if (pin < 0) {
+		return {{SupplicantStatusCode::FAILURE_UNKNOWN, ""}, ""};
+	}
+	return {{SupplicantStatusCode::SUCCESS, ""},
+		misc_utils::convertWpsPinToString(pin)};
+}
+
+SupplicantStatus StaIface::cancelWpsInternal()
+{
+	struct wpa_supplicant *wpa_s = retrieveIfacePtr();
+	if (wpas_wps_cancel(wpa_s)) {
+		return {SupplicantStatusCode::FAILURE_UNKNOWN, ""};
+	}
+	return {SupplicantStatusCode::SUCCESS, ""};
+}
+
+SupplicantStatus StaIface::setWpsDeviceNameInternal(const std::string &name)
+{
+	return iface_config_utils::setWpsDeviceName(retrieveIfacePtr(), name);
+}
+
+SupplicantStatus StaIface::setWpsDeviceTypeInternal(
+    const std::array<uint8_t, 8> &type)
+{
+	return iface_config_utils::setWpsDeviceType(retrieveIfacePtr(), type);
+}
+
+SupplicantStatus StaIface::setWpsManufacturerInternal(
+    const std::string &manufacturer)
+{
+	return iface_config_utils::setWpsManufacturer(
+	    retrieveIfacePtr(), manufacturer);
+}
+
+SupplicantStatus StaIface::setWpsModelNameInternal(
+    const std::string &model_name)
+{
+	return iface_config_utils::setWpsModelName(
+	    retrieveIfacePtr(), model_name);
+}
+
+SupplicantStatus StaIface::setWpsModelNumberInternal(
+    const std::string &model_number)
+{
+	return iface_config_utils::setWpsModelNumber(
+	    retrieveIfacePtr(), model_number);
+}
+
+SupplicantStatus StaIface::setWpsSerialNumberInternal(
+    const std::string &serial_number)
+{
+	return iface_config_utils::setWpsSerialNumber(
+	    retrieveIfacePtr(), serial_number);
+}
+
+SupplicantStatus StaIface::setWpsConfigMethodsInternal(uint16_t config_methods)
+{
+	return iface_config_utils::setWpsConfigMethods(
+	    retrieveIfacePtr(), config_methods);
+}
+
+SupplicantStatus StaIface::setExternalSimInternal(bool useExternalSim)
+{
+	return iface_config_utils::setExternalSim(
+	    retrieveIfacePtr(), useExternalSim);
+}
+
+std::pair<SupplicantStatus, uint32_t> StaIface::addExtRadioWorkInternal(
+    const std::string &name, uint32_t freq_in_mhz, uint32_t timeout_in_sec)
+{
+	struct wpa_supplicant *wpa_s = retrieveIfacePtr();
+	auto *ework = static_cast<struct wpa_external_work *>(
+	    os_zalloc(sizeof(struct wpa_external_work)));
+	if (!ework) {
+		return {{SupplicantStatusCode::FAILURE_UNKNOWN, ""},
+			UINT32_MAX};
+	}
+
+	std::string radio_work_name = kExtRadioWorkNamePrefix + name;
+	os_strlcpy(ework->type, radio_work_name.c_str(), sizeof(ework->type));
+	ework->timeout = timeout_in_sec;
+	wpa_s->ext_work_id++;
+	if (wpa_s->ext_work_id == 0) {
+		wpa_s->ext_work_id++;
+	}
+	ework->id = wpa_s->ext_work_id;
+
+	if (radio_add_work(
+		wpa_s, freq_in_mhz, ework->type, 0, extRadioWorkStartCb,
+		ework)) {
+		os_free(ework);
+		return {{SupplicantStatusCode::FAILURE_UNKNOWN, ""},
+			UINT32_MAX};
+	}
+	return {SupplicantStatus{SupplicantStatusCode::SUCCESS, ""}, ework->id};
+}
+
+SupplicantStatus StaIface::removeExtRadioWorkInternal(uint32_t id)
+{
+	struct wpa_supplicant *wpa_s = retrieveIfacePtr();
+	struct wpa_radio_work *work;
+	dl_list_for_each(work, &wpa_s->radio->work, struct wpa_radio_work, list)
+	{
+		if (os_strncmp(
+			work->type, kExtRadioWorkNamePrefix,
+			sizeof(kExtRadioWorkNamePrefix)) != 0)
+			continue;
+
+		auto *ework =
+		    static_cast<struct wpa_external_work *>(work->ctx);
+		if (ework->id != id)
+			continue;
+
+		wpa_dbg(
+		    wpa_s, MSG_DEBUG, "Completed external radio work %u (%s)",
+		    ework->id, ework->type);
+		eloop_cancel_timeout(extRadioWorkTimeoutCb, work, NULL);
+		endExtRadioWork(work);
+
+		return {SupplicantStatusCode::SUCCESS, ""};
+	}
+	return {SupplicantStatusCode::FAILURE_UNKNOWN, ""};
+}
+
+SupplicantStatus StaIface::enableAutoReconnectInternal(bool enable)
+{
+	struct wpa_supplicant *wpa_s = retrieveIfacePtr();
+	wpa_s->auto_reconnect_disabled = enable ? 0 : 1;
+	return {SupplicantStatusCode::SUCCESS, ""};
+}
+
+/**
+ * Retrieve the underlying |wpa_supplicant| struct
+ * pointer for this iface.
+ * If the underlying iface is removed, then all RPC method calls on this object
+ * will return failure.
+ */
+wpa_supplicant *StaIface::retrieveIfacePtr()
+{
+	return wpa_supplicant_get_iface(wpa_global_, ifname_.c_str());
+}
+}  // namespace implementation
+}  // namespace V1_1
+}  // namespace wifi
+}  // namespace supplicant
+}  // namespace hardware
+}  // namespace android
diff --git a/wpa_supplicant/hidl/1.1/sta_iface.h b/wpa_supplicant/hidl/1.1/sta_iface.h
new file mode 100644
index 0000000..1f1e64b
--- /dev/null
+++ b/wpa_supplicant/hidl/1.1/sta_iface.h
@@ -0,0 +1,255 @@
+/*
+ * 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_STA_IFACE_H
+#define WPA_SUPPLICANT_HIDL_STA_IFACE_H
+
+#include <array>
+#include <vector>
+
+#include <android-base/macros.h>
+
+#include <android/hardware/wifi/supplicant/1.1/ISupplicantStaIface.h>
+#include <android/hardware/wifi/supplicant/1.1/ISupplicantStaIfaceCallback.h>
+#include <android/hardware/wifi/supplicant/1.0/ISupplicantStaNetwork.h>
+
+extern "C" {
+#include "utils/common.h"
+#include "utils/includes.h"
+#include "wpa_supplicant_i.h"
+#include "config.h"
+#include "driver_i.h"
+#include "wpa.h"
+}
+
+namespace android {
+namespace hardware {
+namespace wifi {
+namespace supplicant {
+namespace V1_1 {
+namespace implementation {
+using namespace android::hardware::wifi::supplicant::V1_0;
+
+/**
+ * Implementation of StaIface hidl object. Each unique hidl
+ * object is used for control operations on a specific interface
+ * controlled by wpa_supplicant.
+ */
+class StaIface : public ISupplicantStaIface
+{
+public:
+	StaIface(struct wpa_global* wpa_global, const char ifname[]);
+	~StaIface() override = default;
+	// HIDL does not provide a built-in mechanism to let the server
+	// invalidate a HIDL interface object after creation. If any client
+	// process holds onto a reference to the object in their context,
+	// any method calls on that reference will continue to be directed to
+	// the server.
+	// However Supplicant HAL needs to control the lifetime of these
+	// objects. So, add a public |invalidate| method to all |Iface| and
+	// |Network| objects.
+	// This will be used to mark an object invalid when the corresponding
+	// iface or network is removed.
+	// All HIDL method implementations should check if the object is still
+	// marked valid before processing them.
+	void invalidate();
+	bool isValid();
+
+	// Hidl methods exposed.
+	Return<void> getName(getName_cb _hidl_cb) override;
+	Return<void> getType(getType_cb _hidl_cb) override;
+	Return<void> addNetwork(addNetwork_cb _hidl_cb) override;
+	Return<void> removeNetwork(
+	    SupplicantNetworkId id, removeNetwork_cb _hidl_cb) override;
+	Return<void> getNetwork(
+	    SupplicantNetworkId id, getNetwork_cb _hidl_cb) override;
+	Return<void> listNetworks(listNetworks_cb _hidl_cb) override;
+	Return<void> registerCallback(
+	    const sp<android::hardware::wifi::supplicant::V1_0::ISupplicantStaIfaceCallback>
+	    & callback, registerCallback_cb _hidl_cb) override;
+	Return<void> registerCallback_1_1(
+	    const sp<ISupplicantStaIfaceCallback>& callback,
+	    registerCallback_cb _hidl_cb) override;
+	Return<void> reassociate(reassociate_cb _hidl_cb) override;
+	Return<void> reconnect(reconnect_cb _hidl_cb) override;
+	Return<void> disconnect(disconnect_cb _hidl_cb) override;
+	Return<void> setPowerSave(
+	    bool enable, setPowerSave_cb _hidl_cb) override;
+	Return<void> initiateTdlsDiscover(
+	    const hidl_array<uint8_t, 6>& mac_address,
+	    initiateTdlsDiscover_cb _hidl_cb) override;
+	Return<void> initiateTdlsSetup(
+	    const hidl_array<uint8_t, 6>& mac_address,
+	    initiateTdlsSetup_cb _hidl_cb) override;
+	Return<void> initiateTdlsTeardown(
+	    const hidl_array<uint8_t, 6>& mac_address,
+	    initiateTdlsTeardown_cb _hidl_cb) override;
+	Return<void> initiateAnqpQuery(
+	    const hidl_array<uint8_t, 6>& mac_address,
+	    const hidl_vec<ISupplicantStaIface::AnqpInfoId>& info_elements,
+	    const hidl_vec<ISupplicantStaIface::Hs20AnqpSubtypes>& sub_types,
+	    initiateAnqpQuery_cb _hidl_cb) override;
+	Return<void> initiateHs20IconQuery(
+	    const hidl_array<uint8_t, 6>& mac_address,
+	    const hidl_string& file_name,
+	    initiateHs20IconQuery_cb _hidl_cb) override;
+	Return<void> getMacAddress(getMacAddress_cb _hidl_cb) override;
+	Return<void> startRxFilter(startRxFilter_cb _hidl_cb) override;
+	Return<void> stopRxFilter(stopRxFilter_cb _hidl_cb) override;
+	Return<void> addRxFilter(
+	    ISupplicantStaIface::RxFilterType type,
+	    addRxFilter_cb _hidl_cb) override;
+	Return<void> removeRxFilter(
+	    ISupplicantStaIface::RxFilterType type,
+	    removeRxFilter_cb _hidl_cb) override;
+	Return<void> setBtCoexistenceMode(
+	    ISupplicantStaIface::BtCoexistenceMode mode,
+	    setBtCoexistenceMode_cb _hidl_cb) override;
+	Return<void> setBtCoexistenceScanModeEnabled(
+	    bool enable, setBtCoexistenceScanModeEnabled_cb _hidl_cb) override;
+	Return<void> setSuspendModeEnabled(
+	    bool enable, setSuspendModeEnabled_cb _hidl_cb) override;
+	Return<void> setCountryCode(
+	    const hidl_array<int8_t, 2>& code,
+	    setCountryCode_cb _hidl_cb) override;
+	Return<void> startWpsRegistrar(
+	    const hidl_array<uint8_t, 6>& bssid, const hidl_string& pin,
+	    startWpsRegistrar_cb _hidl_cb) override;
+	Return<void> startWpsPbc(
+	    const hidl_array<uint8_t, 6>& bssid,
+	    startWpsPbc_cb _hidl_cb) override;
+	Return<void> startWpsPinKeypad(
+	    const hidl_string& pin, startWpsPinKeypad_cb _hidl_cb) override;
+	Return<void> startWpsPinDisplay(
+	    const hidl_array<uint8_t, 6>& bssid,
+	    startWpsPinDisplay_cb _hidl_cb) override;
+	Return<void> cancelWps(cancelWps_cb _hidl_cb) override;
+	Return<void> setWpsDeviceName(
+	    const hidl_string& name, setWpsDeviceName_cb _hidl_cb) override;
+	Return<void> setWpsDeviceType(
+	    const hidl_array<uint8_t, 8>& type,
+	    setWpsDeviceType_cb _hidl_cb) override;
+	Return<void> setWpsManufacturer(
+	    const hidl_string& manufacturer,
+	    setWpsManufacturer_cb _hidl_cb) override;
+	Return<void> setWpsModelName(
+	    const hidl_string& model_name,
+	    setWpsModelName_cb _hidl_cb) override;
+	Return<void> setWpsModelNumber(
+	    const hidl_string& model_number,
+	    setWpsModelNumber_cb _hidl_cb) override;
+	Return<void> setWpsSerialNumber(
+	    const hidl_string& serial_number,
+	    setWpsSerialNumber_cb _hidl_cb) override;
+	Return<void> setWpsConfigMethods(
+	    uint16_t config_methods, setWpsConfigMethods_cb _hidl_cb) override;
+	Return<void> setExternalSim(
+	    bool useExternalSim, setExternalSim_cb _hidl_cb) override;
+	Return<void> addExtRadioWork(
+	    const hidl_string& name, uint32_t freq_in_mhz,
+	    uint32_t timeout_in_sec, addExtRadioWork_cb _hidl_cb) override;
+	Return<void> removeExtRadioWork(
+	    uint32_t id, removeExtRadioWork_cb _hidl_cb) override;
+	Return<void> enableAutoReconnect(
+	    bool enable, enableAutoReconnect_cb _hidl_cb) override;
+
+private:
+	// Corresponding worker functions for the HIDL methods.
+	std::pair<SupplicantStatus, std::string> getNameInternal();
+	std::pair<SupplicantStatus, IfaceType> getTypeInternal();
+	std::pair<SupplicantStatus, sp<ISupplicantNetwork>>
+	addNetworkInternal();
+	SupplicantStatus removeNetworkInternal(SupplicantNetworkId id);
+	std::pair<SupplicantStatus, sp<ISupplicantNetwork>> getNetworkInternal(
+	    SupplicantNetworkId id);
+	std::pair<SupplicantStatus, std::vector<SupplicantNetworkId>>
+	listNetworksInternal();
+	SupplicantStatus registerCallbackInternal(
+	    const sp<android::hardware::wifi::supplicant::V1_0::ISupplicantStaIfaceCallback>
+	    & callback);
+	SupplicantStatus registerCallbackInternal_1_1(
+	    const sp<ISupplicantStaIfaceCallback>& callback);
+	SupplicantStatus reassociateInternal();
+	SupplicantStatus reconnectInternal();
+	SupplicantStatus disconnectInternal();
+	SupplicantStatus setPowerSaveInternal(bool enable);
+	SupplicantStatus initiateTdlsDiscoverInternal(
+	    const std::array<uint8_t, 6>& mac_address);
+	SupplicantStatus initiateTdlsSetupInternal(
+	    const std::array<uint8_t, 6>& mac_address);
+	SupplicantStatus initiateTdlsTeardownInternal(
+	    const std::array<uint8_t, 6>& mac_address);
+	SupplicantStatus initiateAnqpQueryInternal(
+	    const std::array<uint8_t, 6>& mac_address,
+	    const std::vector<ISupplicantStaIface::AnqpInfoId>& info_elements,
+	    const std::vector<ISupplicantStaIface::Hs20AnqpSubtypes>&
+		sub_types);
+	SupplicantStatus initiateHs20IconQueryInternal(
+	    const std::array<uint8_t, 6>& mac_address,
+	    const std::string& file_name);
+	std::pair<SupplicantStatus, std::array<uint8_t, 6>>
+	getMacAddressInternal();
+	SupplicantStatus startRxFilterInternal();
+	SupplicantStatus stopRxFilterInternal();
+	SupplicantStatus addRxFilterInternal(
+	    ISupplicantStaIface::RxFilterType type);
+	SupplicantStatus removeRxFilterInternal(
+	    ISupplicantStaIface::RxFilterType type);
+	SupplicantStatus setBtCoexistenceModeInternal(
+	    ISupplicantStaIface::BtCoexistenceMode mode);
+	SupplicantStatus setBtCoexistenceScanModeEnabledInternal(bool enable);
+	SupplicantStatus setSuspendModeEnabledInternal(bool enable);
+	SupplicantStatus setCountryCodeInternal(
+	    const std::array<int8_t, 2>& code);
+	SupplicantStatus startWpsRegistrarInternal(
+	    const std::array<uint8_t, 6>& bssid, const std::string& pin);
+	SupplicantStatus startWpsPbcInternal(
+	    const std::array<uint8_t, 6>& bssid);
+	SupplicantStatus startWpsPinKeypadInternal(const std::string& pin);
+	std::pair<SupplicantStatus, std::string> startWpsPinDisplayInternal(
+	    const std::array<uint8_t, 6>& bssid);
+	SupplicantStatus cancelWpsInternal();
+	SupplicantStatus setWpsDeviceNameInternal(const std::string& name);
+	SupplicantStatus setWpsDeviceTypeInternal(
+	    const std::array<uint8_t, 8>& type);
+	SupplicantStatus setWpsManufacturerInternal(
+	    const std::string& manufacturer);
+	SupplicantStatus setWpsModelNameInternal(const std::string& model_name);
+	SupplicantStatus setWpsModelNumberInternal(
+	    const std::string& model_number);
+	SupplicantStatus setWpsSerialNumberInternal(
+	    const std::string& serial_number);
+	SupplicantStatus setWpsConfigMethodsInternal(uint16_t config_methods);
+	SupplicantStatus setExternalSimInternal(bool useExternalSim);
+	std::pair<SupplicantStatus, uint32_t> addExtRadioWorkInternal(
+	    const std::string& name, uint32_t freq_in_mhz,
+	    uint32_t timeout_in_sec);
+	SupplicantStatus removeExtRadioWorkInternal(uint32_t id);
+	SupplicantStatus enableAutoReconnectInternal(bool enable);
+
+	struct wpa_supplicant* retrieveIfacePtr();
+
+	// Reference to the global wpa_struct. This is assumed to be valid for
+	// the lifetime of the process.
+	struct wpa_global* wpa_global_;
+	// Name of the iface this hidl object controls
+	const std::string ifname_;
+	bool is_valid_;
+
+	DISALLOW_COPY_AND_ASSIGN(StaIface);
+};
+
+}  // namespace implementation
+}  // namespace V1_1
+}  // namespace wifi
+}  // namespace supplicant
+}  // namespace hardware
+}  // namespace android
+
+#endif  // WPA_SUPPLICANT_HIDL_STA_IFACE_H
diff --git a/wpa_supplicant/hidl/1.1/sta_network.cpp b/wpa_supplicant/hidl/1.1/sta_network.cpp
new file mode 100644
index 0000000..9d4cc91
--- /dev/null
+++ b/wpa_supplicant/hidl/1.1/sta_network.cpp
@@ -0,0 +1,1888 @@
+/*
+ * hidl interface for wpa_supplicant daemon
+ * Copyright (c) 2004-2016, Jouni Malinen <j@w1.fi>
+ * Copyright (c) 2004-2016, Roshan Pius <rpius@google.com>
+ *
+ * This software may be distributed under the terms of the BSD license.
+ * See README for more details.
+ */
+
+#include "hidl_manager.h"
+#include "hidl_return_util.h"
+#include "misc_utils.h"
+#include "sta_network.h"
+
+extern "C" {
+#include "wps_supplicant.h"
+}
+
+namespace {
+using android::hardware::wifi::supplicant::V1_0::ISupplicantStaNetwork;
+using android::hardware::wifi::supplicant::V1_0::SupplicantStatus;
+
+constexpr uint8_t kZeroBssid[6] = {0, 0, 0, 0, 0, 0};
+
+constexpr uint32_t kAllowedKeyMgmtMask =
+    (static_cast<uint32_t>(ISupplicantStaNetwork::KeyMgmtMask::NONE) |
+     static_cast<uint32_t>(ISupplicantStaNetwork::KeyMgmtMask::WPA_PSK) |
+     static_cast<uint32_t>(ISupplicantStaNetwork::KeyMgmtMask::WPA_EAP) |
+     static_cast<uint32_t>(ISupplicantStaNetwork::KeyMgmtMask::IEEE8021X) |
+     static_cast<uint32_t>(ISupplicantStaNetwork::KeyMgmtMask::FT_EAP) |
+     static_cast<uint32_t>(ISupplicantStaNetwork::KeyMgmtMask::FT_PSK) |
+     static_cast<uint32_t>(ISupplicantStaNetwork::KeyMgmtMask::OSEN));
+constexpr uint32_t kAllowedProtoMask =
+    (static_cast<uint32_t>(ISupplicantStaNetwork::ProtoMask::WPA) |
+     static_cast<uint32_t>(ISupplicantStaNetwork::ProtoMask::RSN) |
+     static_cast<uint32_t>(ISupplicantStaNetwork::ProtoMask::OSEN));
+constexpr uint32_t kAllowedAuthAlgMask =
+    (static_cast<uint32_t>(ISupplicantStaNetwork::AuthAlgMask::OPEN) |
+     static_cast<uint32_t>(ISupplicantStaNetwork::AuthAlgMask::SHARED) |
+     static_cast<uint32_t>(ISupplicantStaNetwork::AuthAlgMask::LEAP));
+constexpr uint32_t kAllowedGroupCipherMask =
+    (static_cast<uint32_t>(ISupplicantStaNetwork::GroupCipherMask::WEP40) |
+     static_cast<uint32_t>(ISupplicantStaNetwork::GroupCipherMask::WEP104) |
+     static_cast<uint32_t>(ISupplicantStaNetwork::GroupCipherMask::TKIP) |
+     static_cast<uint32_t>(ISupplicantStaNetwork::GroupCipherMask::CCMP) |
+     static_cast<uint32_t>(
+	 ISupplicantStaNetwork::GroupCipherMask::GTK_NOT_USED));
+constexpr uint32_t kAllowedPairwisewCipherMask =
+    (static_cast<uint32_t>(ISupplicantStaNetwork::PairwiseCipherMask::NONE) |
+     static_cast<uint32_t>(ISupplicantStaNetwork::PairwiseCipherMask::TKIP) |
+     static_cast<uint32_t>(ISupplicantStaNetwork::PairwiseCipherMask::CCMP));
+
+constexpr uint32_t kEapMethodMax =
+    static_cast<uint32_t>(ISupplicantStaNetwork::EapMethod::WFA_UNAUTH_TLS) + 1;
+constexpr char const *kEapMethodStrings[kEapMethodMax] = {
+    "PEAP", "TLS", "TTLS", "PWD", "SIM", "AKA", "AKA'", "WFA-UNAUTH-TLS"};
+constexpr uint32_t kEapPhase2MethodMax =
+    static_cast<uint32_t>(ISupplicantStaNetwork::EapPhase2Method::AKA_PRIME) +
+    1;
+constexpr char const *kEapPhase2MethodStrings[kEapPhase2MethodMax] = {
+    "", "PAP", "MSCHAP", "MSCHAPV2", "GTC", "SIM", "AKA", "AKA'"};
+constexpr char kEapPhase2AuthPrefix[] = "auth=";
+constexpr char kEapPhase2AuthEapPrefix[] = "autheap=";
+constexpr char kNetworkEapSimGsmAuthResponse[] = "GSM-AUTH";
+constexpr char kNetworkEapSimUmtsAuthResponse[] = "UMTS-AUTH";
+constexpr char kNetworkEapSimUmtsAutsResponse[] = "UMTS-AUTS";
+constexpr char kNetworkEapSimGsmAuthFailure[] = "GSM-FAIL";
+constexpr char kNetworkEapSimUmtsAuthFailure[] = "UMTS-FAIL";
+}  // namespace
+
+namespace android {
+namespace hardware {
+namespace wifi {
+namespace supplicant {
+namespace V1_1 {
+namespace implementation {
+using hidl_return_util::validateAndCall;
+
+StaNetwork::StaNetwork(
+    struct wpa_global *wpa_global, const char ifname[], int network_id)
+    : wpa_global_(wpa_global),
+      ifname_(ifname),
+      network_id_(network_id),
+      is_valid_(true)
+{
+}
+
+void StaNetwork::invalidate() { is_valid_ = false; }
+bool StaNetwork::isValid()
+{
+	return (is_valid_ && (retrieveNetworkPtr() != nullptr));
+}
+
+Return<void> StaNetwork::getId(getId_cb _hidl_cb)
+{
+	return validateAndCall(
+	    this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
+	    &StaNetwork::getIdInternal, _hidl_cb);
+}
+
+Return<void> StaNetwork::getInterfaceName(getInterfaceName_cb _hidl_cb)
+{
+	return validateAndCall(
+	    this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
+	    &StaNetwork::getInterfaceNameInternal, _hidl_cb);
+}
+
+Return<void> StaNetwork::getType(getType_cb _hidl_cb)
+{
+	return validateAndCall(
+	    this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
+	    &StaNetwork::getTypeInternal, _hidl_cb);
+}
+
+Return<void> StaNetwork::registerCallback(
+    const sp<ISupplicantStaNetworkCallback> &callback,
+    registerCallback_cb _hidl_cb)
+{
+	return validateAndCall(
+	    this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
+	    &StaNetwork::registerCallbackInternal, _hidl_cb, callback);
+}
+
+Return<void> StaNetwork::setSsid(
+    const hidl_vec<uint8_t> &ssid, setSsid_cb _hidl_cb)
+{
+	return validateAndCall(
+	    this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
+	    &StaNetwork::setSsidInternal, _hidl_cb, ssid);
+}
+
+Return<void> StaNetwork::setBssid(
+    const hidl_array<uint8_t, 6> &bssid, setBssid_cb _hidl_cb)
+{
+	return validateAndCall(
+	    this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
+	    &StaNetwork::setBssidInternal, _hidl_cb, bssid);
+}
+
+Return<void> StaNetwork::setScanSsid(bool enable, setScanSsid_cb _hidl_cb)
+{
+	return validateAndCall(
+	    this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
+	    &StaNetwork::setScanSsidInternal, _hidl_cb, enable);
+}
+
+Return<void> StaNetwork::setKeyMgmt(
+    uint32_t key_mgmt_mask, setKeyMgmt_cb _hidl_cb)
+{
+	return validateAndCall(
+	    this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
+	    &StaNetwork::setKeyMgmtInternal, _hidl_cb, key_mgmt_mask);
+}
+
+Return<void> StaNetwork::setProto(uint32_t proto_mask, setProto_cb _hidl_cb)
+{
+	return validateAndCall(
+	    this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
+	    &StaNetwork::setProtoInternal, _hidl_cb, proto_mask);
+}
+
+Return<void> StaNetwork::setAuthAlg(
+    uint32_t auth_alg_mask,
+    std::function<void(const SupplicantStatus &status)> _hidl_cb)
+{
+	return validateAndCall(
+	    this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
+	    &StaNetwork::setAuthAlgInternal, _hidl_cb, auth_alg_mask);
+}
+
+Return<void> StaNetwork::setGroupCipher(
+    uint32_t group_cipher_mask, setGroupCipher_cb _hidl_cb)
+{
+	return validateAndCall(
+	    this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
+	    &StaNetwork::setGroupCipherInternal, _hidl_cb, group_cipher_mask);
+}
+
+Return<void> StaNetwork::setPairwiseCipher(
+    uint32_t pairwise_cipher_mask, setPairwiseCipher_cb _hidl_cb)
+{
+	return validateAndCall(
+	    this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
+	    &StaNetwork::setPairwiseCipherInternal, _hidl_cb,
+	    pairwise_cipher_mask);
+}
+
+Return<void> StaNetwork::setPskPassphrase(
+    const hidl_string &psk, setPskPassphrase_cb _hidl_cb)
+{
+	return validateAndCall(
+	    this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
+	    &StaNetwork::setPskPassphraseInternal, _hidl_cb, psk);
+}
+
+Return<void> StaNetwork::setPsk(
+    const hidl_array<uint8_t, 32> &psk, setPsk_cb _hidl_cb)
+{
+	return validateAndCall(
+	    this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
+	    &StaNetwork::setPskInternal, _hidl_cb, psk);
+}
+
+Return<void> StaNetwork::setWepKey(
+    uint32_t key_idx, const hidl_vec<uint8_t> &wep_key, setWepKey_cb _hidl_cb)
+{
+	return validateAndCall(
+	    this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
+	    &StaNetwork::setWepKeyInternal, _hidl_cb, key_idx, wep_key);
+}
+
+Return<void> StaNetwork::setWepTxKeyIdx(
+    uint32_t key_idx, setWepTxKeyIdx_cb _hidl_cb)
+{
+	return validateAndCall(
+	    this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
+	    &StaNetwork::setWepTxKeyIdxInternal, _hidl_cb, key_idx);
+}
+
+Return<void> StaNetwork::setRequirePmf(bool enable, setRequirePmf_cb _hidl_cb)
+{
+	return validateAndCall(
+	    this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
+	    &StaNetwork::setRequirePmfInternal, _hidl_cb, enable);
+}
+
+Return<void> StaNetwork::setEapMethod(
+    ISupplicantStaNetwork::EapMethod method, setEapMethod_cb _hidl_cb)
+{
+	return validateAndCall(
+	    this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
+	    &StaNetwork::setEapMethodInternal, _hidl_cb, method);
+}
+
+Return<void> StaNetwork::setEapPhase2Method(
+    ISupplicantStaNetwork::EapPhase2Method method,
+    setEapPhase2Method_cb _hidl_cb)
+{
+	return validateAndCall(
+	    this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
+	    &StaNetwork::setEapPhase2MethodInternal, _hidl_cb, method);
+}
+
+Return<void> StaNetwork::setEapIdentity(
+    const hidl_vec<uint8_t> &identity, setEapIdentity_cb _hidl_cb)
+{
+	return validateAndCall(
+	    this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
+	    &StaNetwork::setEapIdentityInternal, _hidl_cb, identity);
+}
+
+Return<void> StaNetwork::setEapEncryptedImsiIdentity(
+    const EapSimEncryptedIdentity &identity, setEapEncryptedImsiIdentity_cb _hidl_cb)
+{
+	return validateAndCall(
+	    this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
+	    &StaNetwork::setEapEncryptedImsiIdentityInternal, _hidl_cb, identity);
+}
+
+Return<void> StaNetwork::setEapAnonymousIdentity(
+    const hidl_vec<uint8_t> &identity, setEapAnonymousIdentity_cb _hidl_cb)
+{
+	return validateAndCall(
+	    this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
+	    &StaNetwork::setEapAnonymousIdentityInternal, _hidl_cb, identity);
+}
+
+Return<void> StaNetwork::setEapPassword(
+    const hidl_vec<uint8_t> &password, setEapPassword_cb _hidl_cb)
+{
+	return validateAndCall(
+	    this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
+	    &StaNetwork::setEapPasswordInternal, _hidl_cb, password);
+}
+
+Return<void> StaNetwork::setEapCACert(
+    const hidl_string &path, setEapCACert_cb _hidl_cb)
+{
+	return validateAndCall(
+	    this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
+	    &StaNetwork::setEapCACertInternal, _hidl_cb, path);
+}
+
+Return<void> StaNetwork::setEapCAPath(
+    const hidl_string &path, setEapCAPath_cb _hidl_cb)
+{
+	return validateAndCall(
+	    this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
+	    &StaNetwork::setEapCAPathInternal, _hidl_cb, path);
+}
+
+Return<void> StaNetwork::setEapClientCert(
+    const hidl_string &path, setEapClientCert_cb _hidl_cb)
+{
+	return validateAndCall(
+	    this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
+	    &StaNetwork::setEapClientCertInternal, _hidl_cb, path);
+}
+
+Return<void> StaNetwork::setEapPrivateKeyId(
+    const hidl_string &id, setEapPrivateKeyId_cb _hidl_cb)
+{
+	return validateAndCall(
+	    this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
+	    &StaNetwork::setEapPrivateKeyIdInternal, _hidl_cb, id);
+}
+
+Return<void> StaNetwork::setEapSubjectMatch(
+    const hidl_string &match, setEapSubjectMatch_cb _hidl_cb)
+{
+	return validateAndCall(
+	    this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
+	    &StaNetwork::setEapSubjectMatchInternal, _hidl_cb, match);
+}
+
+Return<void> StaNetwork::setEapAltSubjectMatch(
+    const hidl_string &match, setEapAltSubjectMatch_cb _hidl_cb)
+{
+	return validateAndCall(
+	    this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
+	    &StaNetwork::setEapAltSubjectMatchInternal, _hidl_cb, match);
+}
+
+Return<void> StaNetwork::setEapEngine(bool enable, setEapEngine_cb _hidl_cb)
+{
+	return validateAndCall(
+	    this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
+	    &StaNetwork::setEapEngineInternal, _hidl_cb, enable);
+}
+
+Return<void> StaNetwork::setEapEngineID(
+    const hidl_string &id, setEapEngineID_cb _hidl_cb)
+{
+	return validateAndCall(
+	    this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
+	    &StaNetwork::setEapEngineIDInternal, _hidl_cb, id);
+}
+
+Return<void> StaNetwork::setEapDomainSuffixMatch(
+    const hidl_string &match, setEapDomainSuffixMatch_cb _hidl_cb)
+{
+	return validateAndCall(
+	    this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
+	    &StaNetwork::setEapDomainSuffixMatchInternal, _hidl_cb, match);
+}
+
+Return<void> StaNetwork::setProactiveKeyCaching(
+    bool enable, setProactiveKeyCaching_cb _hidl_cb)
+{
+	return validateAndCall(
+	    this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
+	    &StaNetwork::setProactiveKeyCachingInternal, _hidl_cb, enable);
+}
+
+Return<void> StaNetwork::setIdStr(
+    const hidl_string &id_str, setIdStr_cb _hidl_cb)
+{
+	return validateAndCall(
+	    this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
+	    &StaNetwork::setIdStrInternal, _hidl_cb, id_str);
+}
+
+Return<void> StaNetwork::setUpdateIdentifier(
+    uint32_t id, setUpdateIdentifier_cb _hidl_cb)
+{
+	return validateAndCall(
+	    this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
+	    &StaNetwork::setUpdateIdentifierInternal, _hidl_cb, id);
+}
+
+Return<void> StaNetwork::getSsid(getSsid_cb _hidl_cb)
+{
+	return validateAndCall(
+	    this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
+	    &StaNetwork::getSsidInternal, _hidl_cb);
+}
+
+Return<void> StaNetwork::getBssid(getBssid_cb _hidl_cb)
+{
+	return validateAndCall(
+	    this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
+	    &StaNetwork::getBssidInternal, _hidl_cb);
+}
+
+Return<void> StaNetwork::getScanSsid(getScanSsid_cb _hidl_cb)
+{
+	return validateAndCall(
+	    this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
+	    &StaNetwork::getScanSsidInternal, _hidl_cb);
+}
+
+Return<void> StaNetwork::getKeyMgmt(getKeyMgmt_cb _hidl_cb)
+{
+	return validateAndCall(
+	    this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
+	    &StaNetwork::getKeyMgmtInternal, _hidl_cb);
+}
+
+Return<void> StaNetwork::getProto(getProto_cb _hidl_cb)
+{
+	return validateAndCall(
+	    this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
+	    &StaNetwork::getProtoInternal, _hidl_cb);
+}
+
+Return<void> StaNetwork::getAuthAlg(getAuthAlg_cb _hidl_cb)
+{
+	return validateAndCall(
+	    this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
+	    &StaNetwork::getAuthAlgInternal, _hidl_cb);
+}
+
+Return<void> StaNetwork::getGroupCipher(getGroupCipher_cb _hidl_cb)
+{
+	return validateAndCall(
+	    this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
+	    &StaNetwork::getGroupCipherInternal, _hidl_cb);
+}
+
+Return<void> StaNetwork::getPairwiseCipher(getPairwiseCipher_cb _hidl_cb)
+{
+	return validateAndCall(
+	    this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
+	    &StaNetwork::getPairwiseCipherInternal, _hidl_cb);
+}
+
+Return<void> StaNetwork::getPskPassphrase(getPskPassphrase_cb _hidl_cb)
+{
+	return validateAndCall(
+	    this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
+	    &StaNetwork::getPskPassphraseInternal, _hidl_cb);
+}
+
+Return<void> StaNetwork::getPsk(getPsk_cb _hidl_cb)
+{
+	return validateAndCall(
+	    this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
+	    &StaNetwork::getPskInternal, _hidl_cb);
+}
+
+Return<void> StaNetwork::getWepKey(uint32_t key_idx, getWepKey_cb _hidl_cb)
+{
+	return validateAndCall(
+	    this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
+	    &StaNetwork::getWepKeyInternal, _hidl_cb, key_idx);
+}
+
+Return<void> StaNetwork::getWepTxKeyIdx(getWepTxKeyIdx_cb _hidl_cb)
+{
+	return validateAndCall(
+	    this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
+	    &StaNetwork::getWepTxKeyIdxInternal, _hidl_cb);
+}
+
+Return<void> StaNetwork::getRequirePmf(getRequirePmf_cb _hidl_cb)
+{
+	return validateAndCall(
+	    this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
+	    &StaNetwork::getRequirePmfInternal, _hidl_cb);
+}
+
+Return<void> StaNetwork::getEapMethod(getEapMethod_cb _hidl_cb)
+{
+	return validateAndCall(
+	    this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
+	    &StaNetwork::getEapMethodInternal, _hidl_cb);
+}
+
+Return<void> StaNetwork::getEapPhase2Method(getEapPhase2Method_cb _hidl_cb)
+{
+	return validateAndCall(
+	    this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
+	    &StaNetwork::getEapPhase2MethodInternal, _hidl_cb);
+}
+
+Return<void> StaNetwork::getEapIdentity(getEapIdentity_cb _hidl_cb)
+{
+	return validateAndCall(
+	    this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
+	    &StaNetwork::getEapIdentityInternal, _hidl_cb);
+}
+
+Return<void> StaNetwork::getEapAnonymousIdentity(
+    getEapAnonymousIdentity_cb _hidl_cb)
+{
+	return validateAndCall(
+	    this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
+	    &StaNetwork::getEapAnonymousIdentityInternal, _hidl_cb);
+}
+
+Return<void> StaNetwork::getEapPassword(getEapPassword_cb _hidl_cb)
+{
+	return validateAndCall(
+	    this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
+	    &StaNetwork::getEapPasswordInternal, _hidl_cb);
+}
+
+Return<void> StaNetwork::getEapCACert(getEapCACert_cb _hidl_cb)
+{
+	return validateAndCall(
+	    this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
+	    &StaNetwork::getEapCACertInternal, _hidl_cb);
+}
+
+Return<void> StaNetwork::getEapCAPath(getEapCAPath_cb _hidl_cb)
+{
+	return validateAndCall(
+	    this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
+	    &StaNetwork::getEapCAPathInternal, _hidl_cb);
+}
+
+Return<void> StaNetwork::getEapClientCert(getEapClientCert_cb _hidl_cb)
+{
+	return validateAndCall(
+	    this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
+	    &StaNetwork::getEapClientCertInternal, _hidl_cb);
+}
+
+Return<void> StaNetwork::getEapPrivateKeyId(getEapPrivateKeyId_cb _hidl_cb)
+{
+	return validateAndCall(
+	    this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
+	    &StaNetwork::getEapPrivateKeyIdInternal, _hidl_cb);
+}
+
+Return<void> StaNetwork::getEapSubjectMatch(getEapSubjectMatch_cb _hidl_cb)
+{
+	return validateAndCall(
+	    this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
+	    &StaNetwork::getEapSubjectMatchInternal, _hidl_cb);
+}
+
+Return<void> StaNetwork::getEapAltSubjectMatch(
+    getEapAltSubjectMatch_cb _hidl_cb)
+{
+	return validateAndCall(
+	    this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
+	    &StaNetwork::getEapAltSubjectMatchInternal, _hidl_cb);
+}
+
+Return<void> StaNetwork::getEapEngine(getEapEngine_cb _hidl_cb)
+{
+	return validateAndCall(
+	    this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
+	    &StaNetwork::getEapEngineInternal, _hidl_cb);
+}
+
+Return<void> StaNetwork::getEapEngineID(getEapEngineID_cb _hidl_cb)
+{
+	return validateAndCall(
+	    this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
+	    &StaNetwork::getEapEngineIDInternal, _hidl_cb);
+}
+
+Return<void> StaNetwork::getEapDomainSuffixMatch(
+    getEapDomainSuffixMatch_cb _hidl_cb)
+{
+	return validateAndCall(
+	    this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
+	    &StaNetwork::getEapDomainSuffixMatchInternal, _hidl_cb);
+}
+
+Return<void> StaNetwork::getIdStr(getIdStr_cb _hidl_cb)
+{
+	return validateAndCall(
+	    this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
+	    &StaNetwork::getIdStrInternal, _hidl_cb);
+}
+
+Return<void> StaNetwork::getWpsNfcConfigurationToken(
+    getWpsNfcConfigurationToken_cb _hidl_cb)
+{
+	return validateAndCall(
+	    this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
+	    &StaNetwork::getWpsNfcConfigurationTokenInternal, _hidl_cb);
+}
+
+Return<void> StaNetwork::enable(bool no_connect, enable_cb _hidl_cb)
+{
+	return validateAndCall(
+	    this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
+	    &StaNetwork::enableInternal, _hidl_cb, no_connect);
+}
+
+Return<void> StaNetwork::disable(disable_cb _hidl_cb)
+{
+	return validateAndCall(
+	    this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
+	    &StaNetwork::disableInternal, _hidl_cb);
+}
+
+Return<void> StaNetwork::select(select_cb _hidl_cb)
+{
+	return validateAndCall(
+	    this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
+	    &StaNetwork::selectInternal, _hidl_cb);
+}
+
+Return<void> StaNetwork::sendNetworkEapSimGsmAuthResponse(
+    const hidl_vec<ISupplicantStaNetwork::NetworkResponseEapSimGsmAuthParams>
+	&vec_params,
+    sendNetworkEapSimGsmAuthResponse_cb _hidl_cb)
+{
+	return validateAndCall(
+	    this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
+	    &StaNetwork::sendNetworkEapSimGsmAuthResponseInternal, _hidl_cb,
+	    vec_params);
+}
+
+Return<void> StaNetwork::sendNetworkEapSimGsmAuthFailure(
+    sendNetworkEapSimGsmAuthFailure_cb _hidl_cb)
+{
+	return validateAndCall(
+	    this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
+	    &StaNetwork::sendNetworkEapSimGsmAuthFailureInternal, _hidl_cb);
+}
+
+Return<void> StaNetwork::sendNetworkEapSimUmtsAuthResponse(
+    const ISupplicantStaNetwork::NetworkResponseEapSimUmtsAuthParams &params,
+    sendNetworkEapSimUmtsAuthResponse_cb _hidl_cb)
+{
+	return validateAndCall(
+	    this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
+	    &StaNetwork::sendNetworkEapSimUmtsAuthResponseInternal, _hidl_cb,
+	    params);
+}
+
+Return<void> StaNetwork::sendNetworkEapSimUmtsAutsResponse(
+    const hidl_array<uint8_t, 14> &auts,
+    sendNetworkEapSimUmtsAutsResponse_cb _hidl_cb)
+{
+	return validateAndCall(
+	    this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
+	    &StaNetwork::sendNetworkEapSimUmtsAutsResponseInternal, _hidl_cb,
+	    auts);
+}
+
+Return<void> StaNetwork::sendNetworkEapSimUmtsAuthFailure(
+    sendNetworkEapSimUmtsAuthFailure_cb _hidl_cb)
+{
+	return validateAndCall(
+	    this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
+	    &StaNetwork::sendNetworkEapSimUmtsAuthFailureInternal, _hidl_cb);
+}
+
+Return<void> StaNetwork::sendNetworkEapIdentityResponse(
+    const hidl_vec<uint8_t> &identity,
+    sendNetworkEapIdentityResponse_cb _hidl_cb)
+{
+	return validateAndCall(
+	    this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
+	    &StaNetwork::sendNetworkEapIdentityResponseInternal, _hidl_cb,
+	    identity);
+}
+
+Return<void> StaNetwork::sendNetworkEapIdentityResponse_1_1(
+    const EapSimIdentity &identity,
+    const EapSimEncryptedIdentity &encrypted_imsi_identity,
+    sendNetworkEapIdentityResponse_1_1_cb _hidl_cb)
+{
+	return validateAndCall(
+	    this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
+	    &StaNetwork::sendNetworkEapIdentityResponseInternal_1_1, _hidl_cb,
+	    identity, encrypted_imsi_identity);
+}
+
+std::pair<SupplicantStatus, uint32_t> StaNetwork::getIdInternal()
+{
+	return {{SupplicantStatusCode::SUCCESS, ""}, network_id_};
+}
+
+std::pair<SupplicantStatus, std::string> StaNetwork::getInterfaceNameInternal()
+{
+	return {{SupplicantStatusCode::SUCCESS, ""}, ifname_};
+}
+
+std::pair<SupplicantStatus, IfaceType> StaNetwork::getTypeInternal()
+{
+	return {{SupplicantStatusCode::SUCCESS, ""}, IfaceType::STA};
+}
+
+SupplicantStatus StaNetwork::registerCallbackInternal(
+    const sp<ISupplicantStaNetworkCallback> &callback)
+{
+	HidlManager *hidl_manager = HidlManager::getInstance();
+	if (!hidl_manager ||
+	    hidl_manager->addStaNetworkCallbackHidlObject(
+		ifname_, network_id_, callback)) {
+		return {SupplicantStatusCode::FAILURE_UNKNOWN, ""};
+	}
+	return {SupplicantStatusCode::SUCCESS, ""};
+}
+
+SupplicantStatus StaNetwork::setSsidInternal(const std::vector<uint8_t> &ssid)
+{
+	struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
+	if (ssid.size() == 0 ||
+	    ssid.size() >
+		static_cast<uint32_t>(ISupplicantStaNetwork::ParamSizeLimits::
+					  SSID_MAX_LEN_IN_BYTES)) {
+		return {SupplicantStatusCode::FAILURE_ARGS_INVALID, ""};
+	}
+	if (setByteArrayFieldAndResetState(
+		ssid.data(), ssid.size(), &(wpa_ssid->ssid),
+		&(wpa_ssid->ssid_len), "ssid")) {
+		return {SupplicantStatusCode::FAILURE_UNKNOWN, ""};
+	}
+	if (wpa_ssid->passphrase) {
+		wpa_config_update_psk(wpa_ssid);
+	}
+	return {SupplicantStatusCode::SUCCESS, ""};
+}
+
+SupplicantStatus StaNetwork::setBssidInternal(
+    const std::array<uint8_t, 6> &bssid)
+{
+	struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
+	int prev_bssid_set = wpa_ssid->bssid_set;
+	u8 prev_bssid[ETH_ALEN];
+	os_memcpy(prev_bssid, wpa_ssid->bssid, ETH_ALEN);
+	// Zero'ed array is used to clear out the BSSID value.
+	if (os_memcmp(bssid.data(), kZeroBssid, ETH_ALEN) == 0) {
+		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 {SupplicantStatusCode::SUCCESS, ""};
+}
+
+SupplicantStatus StaNetwork::setScanSsidInternal(bool enable)
+{
+	struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
+	wpa_ssid->scan_ssid = enable ? 1 : 0;
+	resetInternalStateAfterParamsUpdate();
+	return {SupplicantStatusCode::SUCCESS, ""};
+}
+
+SupplicantStatus StaNetwork::setKeyMgmtInternal(uint32_t key_mgmt_mask)
+{
+	struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
+	if (key_mgmt_mask & ~kAllowedKeyMgmtMask) {
+		return {SupplicantStatusCode::FAILURE_ARGS_INVALID, ""};
+	}
+	wpa_ssid->key_mgmt = key_mgmt_mask;
+	wpa_printf(MSG_MSGDUMP, "key_mgmt: 0x%x", wpa_ssid->key_mgmt);
+	resetInternalStateAfterParamsUpdate();
+	return {SupplicantStatusCode::SUCCESS, ""};
+}
+
+SupplicantStatus StaNetwork::setProtoInternal(uint32_t proto_mask)
+{
+	struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
+	if (proto_mask & ~kAllowedProtoMask) {
+		return {SupplicantStatusCode::FAILURE_ARGS_INVALID, ""};
+	}
+	wpa_ssid->proto = proto_mask;
+	wpa_printf(MSG_MSGDUMP, "proto: 0x%x", wpa_ssid->proto);
+	resetInternalStateAfterParamsUpdate();
+	return {SupplicantStatusCode::SUCCESS, ""};
+}
+
+SupplicantStatus StaNetwork::setAuthAlgInternal(uint32_t auth_alg_mask)
+{
+	struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
+	if (auth_alg_mask & ~kAllowedAuthAlgMask) {
+		return {SupplicantStatusCode::FAILURE_ARGS_INVALID, ""};
+	}
+	wpa_ssid->auth_alg = auth_alg_mask;
+	wpa_printf(MSG_MSGDUMP, "auth_alg: 0x%x", wpa_ssid->auth_alg);
+	resetInternalStateAfterParamsUpdate();
+	return {SupplicantStatusCode::SUCCESS, ""};
+}
+
+SupplicantStatus StaNetwork::setGroupCipherInternal(uint32_t group_cipher_mask)
+{
+	struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
+	if (group_cipher_mask & ~kAllowedGroupCipherMask) {
+		return {SupplicantStatusCode::FAILURE_ARGS_INVALID, ""};
+	}
+	wpa_ssid->group_cipher = group_cipher_mask;
+	wpa_printf(MSG_MSGDUMP, "group_cipher: 0x%x", wpa_ssid->group_cipher);
+	resetInternalStateAfterParamsUpdate();
+	return {SupplicantStatusCode::SUCCESS, ""};
+}
+
+SupplicantStatus StaNetwork::setPairwiseCipherInternal(
+    uint32_t pairwise_cipher_mask)
+{
+	struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
+	if (pairwise_cipher_mask & ~kAllowedPairwisewCipherMask) {
+		return {SupplicantStatusCode::FAILURE_ARGS_INVALID, ""};
+	}
+	wpa_ssid->pairwise_cipher = pairwise_cipher_mask;
+	wpa_printf(
+	    MSG_MSGDUMP, "pairwise_cipher: 0x%x", wpa_ssid->pairwise_cipher);
+	resetInternalStateAfterParamsUpdate();
+	return {SupplicantStatusCode::SUCCESS, ""};
+}
+
+SupplicantStatus StaNetwork::setPskPassphraseInternal(const std::string &psk)
+{
+	struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
+	if (isPskPassphraseValid(psk)) {
+		return {SupplicantStatusCode::FAILURE_ARGS_INVALID, ""};
+	}
+	if (wpa_ssid->passphrase &&
+	    os_strlen(wpa_ssid->passphrase) == psk.size() &&
+	    os_memcmp(wpa_ssid->passphrase, psk.c_str(), psk.size()) == 0) {
+		return {SupplicantStatusCode::SUCCESS, ""};
+	}
+	// 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;
+	if (setStringKeyFieldAndResetState(
+		psk.c_str(), &(wpa_ssid->passphrase), "psk passphrase")) {
+		return {SupplicantStatusCode::FAILURE_UNKNOWN, ""};
+	}
+	if (wpa_ssid->ssid_len) {
+		wpa_config_update_psk(wpa_ssid);
+	}
+	return {SupplicantStatusCode::SUCCESS, ""};
+}
+
+SupplicantStatus StaNetwork::setPskInternal(const std::array<uint8_t, 32> &psk)
+{
+	struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
+	WPA_ASSERT(psk.size() == sizeof(wpa_ssid->psk));
+	str_clear_free(wpa_ssid->passphrase);
+	wpa_ssid->passphrase = nullptr;
+	os_memcpy(wpa_ssid->psk, psk.data(), sizeof(wpa_ssid->psk));
+	wpa_ssid->psk_set = 1;
+	resetInternalStateAfterParamsUpdate();
+	return {SupplicantStatusCode::SUCCESS, ""};
+}
+
+SupplicantStatus StaNetwork::setWepKeyInternal(
+    uint32_t key_idx, const std::vector<uint8_t> &wep_key)
+{
+	struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
+	if (key_idx >=
+	    static_cast<uint32_t>(
+		ISupplicantStaNetwork::ParamSizeLimits::WEP_KEYS_MAX_NUM)) {
+		return {SupplicantStatusCode::FAILURE_ARGS_INVALID, ""};
+	}
+	if (wep_key.size() !=
+		static_cast<uint32_t>(ISupplicantStaNetwork::ParamSizeLimits::
+					  WEP40_KEY_LEN_IN_BYTES) &&
+	    wep_key.size() !=
+		static_cast<uint32_t>(ISupplicantStaNetwork::ParamSizeLimits::
+					  WEP104_KEY_LEN_IN_BYTES)) {
+		return {SupplicantStatusCode::FAILURE_ARGS_INVALID, ""};
+	}
+	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 {SupplicantStatusCode::SUCCESS, ""};
+}
+
+SupplicantStatus StaNetwork::setWepTxKeyIdxInternal(uint32_t key_idx)
+{
+	struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
+	if (key_idx >=
+	    static_cast<uint32_t>(
+		ISupplicantStaNetwork::ParamSizeLimits::WEP_KEYS_MAX_NUM)) {
+		return {SupplicantStatusCode::FAILURE_ARGS_INVALID, ""};
+	}
+	wpa_ssid->wep_tx_keyidx = key_idx;
+	resetInternalStateAfterParamsUpdate();
+	return {SupplicantStatusCode::SUCCESS, ""};
+}
+
+SupplicantStatus StaNetwork::setRequirePmfInternal(bool enable)
+{
+	struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
+	wpa_ssid->ieee80211w =
+	    enable ? MGMT_FRAME_PROTECTION_REQUIRED : NO_MGMT_FRAME_PROTECTION;
+	resetInternalStateAfterParamsUpdate();
+	return {SupplicantStatusCode::SUCCESS, ""};
+}
+
+SupplicantStatus StaNetwork::setEapMethodInternal(
+    ISupplicantStaNetwork::EapMethod method)
+{
+	uint32_t eap_method_idx = static_cast<
+	    std::underlying_type<ISupplicantStaNetwork::EapMethod>::type>(
+	    method);
+	if (eap_method_idx >= kEapMethodMax) {
+		return {SupplicantStatusCode::FAILURE_ARGS_INVALID, ""};
+	}
+
+	struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
+	int retrieved_vendor, retrieved_method;
+	const char *method_str = kEapMethodStrings[eap_method_idx];
+	// 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) {
+		return {SupplicantStatusCode::FAILURE_UNKNOWN, ""};
+	}
+	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 {SupplicantStatusCode::FAILURE_UNKNOWN, ""};
+	}
+	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 {SupplicantStatusCode::SUCCESS, ""};
+}
+
+SupplicantStatus StaNetwork::setEapPhase2MethodInternal(
+    ISupplicantStaNetwork::EapPhase2Method method)
+{
+	uint32_t eap_phase2_method_idx = static_cast<
+	    std::underlying_type<ISupplicantStaNetwork::EapPhase2Method>::type>(
+	    method);
+	if (eap_phase2_method_idx >= kEapPhase2MethodMax) {
+		return {SupplicantStatusCode::FAILURE_ARGS_INVALID, ""};
+	}
+
+	struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
+	// EAP method needs to be set for us to construct the eap
+	// phase 2 method string.
+	SupplicantStatus status;
+	ISupplicantStaNetwork::EapMethod eap_method;
+	std::tie(status, eap_method) = getEapMethodInternal();
+	if (status.code != SupplicantStatusCode::SUCCESS) {
+		return {SupplicantStatusCode::FAILURE_UNKNOWN,
+			"EAP method not set"};
+	}
+	std::string eap_phase2_str;
+	if (method == ISupplicantStaNetwork::EapPhase2Method::NONE) {
+		eap_phase2_str = "";
+	} else if (
+	    eap_method == ISupplicantStaNetwork::EapMethod::TTLS &&
+	    method == ISupplicantStaNetwork::EapPhase2Method::GTC) {
+		eap_phase2_str = kEapPhase2AuthEapPrefix;
+	} else {
+		eap_phase2_str = kEapPhase2AuthPrefix;
+	}
+	eap_phase2_str += kEapPhase2MethodStrings[eap_phase2_method_idx];
+	if (setStringFieldAndResetState(
+		eap_phase2_str.c_str(), &(wpa_ssid->eap.phase2),
+		"eap phase2")) {
+		return {SupplicantStatusCode::FAILURE_UNKNOWN, ""};
+	}
+	return {SupplicantStatusCode::SUCCESS, ""};
+}
+
+SupplicantStatus StaNetwork::setEapIdentityInternal(
+    const std::vector<uint8_t> &identity)
+{
+	struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
+	if (setByteArrayFieldAndResetState(
+		identity.data(), identity.size(), &(wpa_ssid->eap.identity),
+		&(wpa_ssid->eap.identity_len), "eap identity")) {
+		return { SupplicantStatusCode::FAILURE_UNKNOWN, ""};
+	}
+	// plain IMSI identity
+	if (setByteArrayFieldAndResetState(
+		identity.data(), identity.size(), &(wpa_ssid->eap.imsi_identity),
+		&(wpa_ssid->eap.imsi_identity_len), "eap imsi identity")) {
+		return { SupplicantStatusCode::FAILURE_UNKNOWN, ""};
+	}
+	return {SupplicantStatusCode::SUCCESS, ""};
+}
+
+SupplicantStatus StaNetwork::setEapEncryptedImsiIdentityInternal(
+    const std::vector<uint8_t> &identity)
+{
+	struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
+	// encrypted IMSI identity
+	if (setByteArrayFieldAndResetState(
+		identity.data(), identity.size(), &(wpa_ssid->eap.identity),
+		&(wpa_ssid->eap.identity_len), "eap encrypted imsi identity")) {
+		return {SupplicantStatusCode::FAILURE_UNKNOWN, ""};
+	}
+	return {SupplicantStatusCode::SUCCESS, ""};
+}
+
+SupplicantStatus StaNetwork::setEapAnonymousIdentityInternal(
+    const std::vector<uint8_t> &identity)
+{
+	struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
+	if (setByteArrayFieldAndResetState(
+		identity.data(), identity.size(),
+		&(wpa_ssid->eap.anonymous_identity),
+		&(wpa_ssid->eap.anonymous_identity_len),
+		"eap anonymous_identity")) {
+		return {SupplicantStatusCode::FAILURE_UNKNOWN, ""};
+	}
+	return {SupplicantStatusCode::SUCCESS, ""};
+}
+
+SupplicantStatus StaNetwork::setEapPasswordInternal(
+    const std::vector<uint8_t> &password)
+{
+	struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
+	if (setByteArrayKeyFieldAndResetState(
+		password.data(), password.size(), &(wpa_ssid->eap.password),
+		&(wpa_ssid->eap.password_len), "eap password")) {
+		return {SupplicantStatusCode::FAILURE_UNKNOWN, ""};
+	}
+	wpa_ssid->eap.flags &= ~EAP_CONFIG_FLAGS_PASSWORD_NTHASH;
+	wpa_ssid->eap.flags &= ~EAP_CONFIG_FLAGS_EXT_PASSWORD;
+	return {SupplicantStatusCode::SUCCESS, ""};
+}
+
+SupplicantStatus StaNetwork::setEapCACertInternal(const std::string &path)
+{
+	struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
+	if (setStringFieldAndResetState(
+		path.c_str(), &(wpa_ssid->eap.ca_cert), "eap ca_cert")) {
+		return {SupplicantStatusCode::FAILURE_UNKNOWN, ""};
+	}
+	return {SupplicantStatusCode::SUCCESS, ""};
+}
+
+SupplicantStatus StaNetwork::setEapCAPathInternal(const std::string &path)
+{
+	struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
+	if (setStringFieldAndResetState(
+		path.c_str(), &(wpa_ssid->eap.ca_path), "eap ca_path")) {
+		return {SupplicantStatusCode::FAILURE_UNKNOWN, ""};
+	}
+	return {SupplicantStatusCode::SUCCESS, ""};
+}
+
+SupplicantStatus StaNetwork::setEapClientCertInternal(const std::string &path)
+{
+	struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
+	if (setStringFieldAndResetState(
+		path.c_str(), &(wpa_ssid->eap.client_cert),
+		"eap client_cert")) {
+		return {SupplicantStatusCode::FAILURE_UNKNOWN, ""};
+	}
+	return {SupplicantStatusCode::SUCCESS, ""};
+}
+
+SupplicantStatus StaNetwork::setEapPrivateKeyIdInternal(const std::string &id)
+{
+	struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
+	if (setStringFieldAndResetState(
+		id.c_str(), &(wpa_ssid->eap.key_id), "eap key_id")) {
+		return {SupplicantStatusCode::FAILURE_UNKNOWN, ""};
+	}
+	return {SupplicantStatusCode::SUCCESS, ""};
+}
+
+SupplicantStatus StaNetwork::setEapSubjectMatchInternal(
+    const std::string &match)
+{
+	struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
+	if (setStringFieldAndResetState(
+		match.c_str(), &(wpa_ssid->eap.subject_match),
+		"eap subject_match")) {
+		return {SupplicantStatusCode::FAILURE_UNKNOWN, ""};
+	}
+	return {SupplicantStatusCode::SUCCESS, ""};
+}
+
+SupplicantStatus StaNetwork::setEapAltSubjectMatchInternal(
+    const std::string &match)
+{
+	struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
+	if (setStringFieldAndResetState(
+		match.c_str(), &(wpa_ssid->eap.altsubject_match),
+		"eap altsubject_match")) {
+		return {SupplicantStatusCode::FAILURE_UNKNOWN, ""};
+	}
+	return {SupplicantStatusCode::SUCCESS, ""};
+}
+
+SupplicantStatus StaNetwork::setEapEngineInternal(bool enable)
+{
+	struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
+	wpa_ssid->eap.engine = enable ? 1 : 0;
+	return {SupplicantStatusCode::SUCCESS, ""};
+}
+
+SupplicantStatus StaNetwork::setEapEngineIDInternal(const std::string &id)
+{
+	struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
+	if (setStringFieldAndResetState(
+		id.c_str(), &(wpa_ssid->eap.engine_id), "eap engine_id")) {
+		return {SupplicantStatusCode::FAILURE_UNKNOWN, ""};
+	}
+	return {SupplicantStatusCode::SUCCESS, ""};
+}
+
+SupplicantStatus StaNetwork::setEapDomainSuffixMatchInternal(
+    const std::string &match)
+{
+	struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
+	if (setStringFieldAndResetState(
+		match.c_str(), &(wpa_ssid->eap.domain_suffix_match),
+		"eap domain_suffix_match")) {
+		return {SupplicantStatusCode::FAILURE_UNKNOWN, ""};
+	}
+	return {SupplicantStatusCode::SUCCESS, ""};
+}
+
+SupplicantStatus StaNetwork::setProactiveKeyCachingInternal(bool enable)
+{
+	struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
+	wpa_ssid->proactive_key_caching = enable ? 1 : 0;
+	resetInternalStateAfterParamsUpdate();
+	return {SupplicantStatusCode::SUCCESS, ""};
+}
+
+SupplicantStatus StaNetwork::setIdStrInternal(const std::string &id_str)
+{
+	struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
+	if (setStringFieldAndResetState(
+		id_str.c_str(), &(wpa_ssid->id_str), "id_str")) {
+		return {SupplicantStatusCode::FAILURE_UNKNOWN, ""};
+	}
+	return {SupplicantStatusCode::SUCCESS, ""};
+}
+
+SupplicantStatus StaNetwork::setUpdateIdentifierInternal(uint32_t id)
+{
+	struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
+	wpa_ssid->update_identifier = id;
+	wpa_printf(
+	    MSG_MSGDUMP, "update_identifier: %d", wpa_ssid->update_identifier);
+	resetInternalStateAfterParamsUpdate();
+	return {SupplicantStatusCode::SUCCESS, ""};
+}
+
+std::pair<SupplicantStatus, std::vector<uint8_t>> StaNetwork::getSsidInternal()
+{
+	struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
+	std::vector<uint8_t> ssid;
+	ssid.assign(wpa_ssid->ssid, wpa_ssid->ssid + wpa_ssid->ssid_len);
+	return {{SupplicantStatusCode::SUCCESS, ""}, std::move(ssid)};
+}
+
+std::pair<SupplicantStatus, std::array<uint8_t, 6>>
+StaNetwork::getBssidInternal()
+{
+	struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
+	std::array<uint8_t, 6> bssid{};
+	os_memcpy(bssid.data(), kZeroBssid, ETH_ALEN);
+	if (wpa_ssid->bssid_set) {
+		os_memcpy(bssid.data(), wpa_ssid->bssid, ETH_ALEN);
+	}
+	return {{SupplicantStatusCode::SUCCESS, ""}, std::move(bssid)};
+}
+
+std::pair<SupplicantStatus, bool> StaNetwork::getScanSsidInternal()
+{
+	struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
+	return {{SupplicantStatusCode::SUCCESS, ""},
+		(wpa_ssid->scan_ssid == 1)};
+}
+
+std::pair<SupplicantStatus, uint32_t> StaNetwork::getKeyMgmtInternal()
+{
+	struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
+	return {{SupplicantStatusCode::SUCCESS, ""},
+		wpa_ssid->key_mgmt & kAllowedKeyMgmtMask};
+}
+
+std::pair<SupplicantStatus, uint32_t> StaNetwork::getProtoInternal()
+{
+	struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
+	return {{SupplicantStatusCode::SUCCESS, ""},
+		wpa_ssid->proto & kAllowedProtoMask};
+}
+
+std::pair<SupplicantStatus, uint32_t> StaNetwork::getAuthAlgInternal()
+{
+	struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
+	return {{SupplicantStatusCode::SUCCESS, ""},
+		wpa_ssid->auth_alg & kAllowedAuthAlgMask};
+}
+
+std::pair<SupplicantStatus, uint32_t> StaNetwork::getGroupCipherInternal()
+{
+	struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
+	return {{SupplicantStatusCode::SUCCESS, ""},
+		wpa_ssid->group_cipher & kAllowedGroupCipherMask};
+}
+
+std::pair<SupplicantStatus, uint32_t> StaNetwork::getPairwiseCipherInternal()
+{
+	struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
+	return {{SupplicantStatusCode::SUCCESS, ""},
+		wpa_ssid->pairwise_cipher & kAllowedPairwisewCipherMask};
+}
+
+std::pair<SupplicantStatus, std::string> StaNetwork::getPskPassphraseInternal()
+{
+	struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
+	if (!wpa_ssid->passphrase) {
+		return {{SupplicantStatusCode::FAILURE_UNKNOWN, ""}, {}};
+	}
+	return {{SupplicantStatusCode::SUCCESS, ""}, wpa_ssid->passphrase};
+}
+
+std::pair<SupplicantStatus, std::array<uint8_t, 32>>
+StaNetwork::getPskInternal()
+{
+	struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
+	WPA_ASSERT(psk.size() == sizeof(wpa_ssid->psk));
+	if (!wpa_ssid->psk_set) {
+		return {{SupplicantStatusCode::FAILURE_UNKNOWN, ""}, {}};
+	}
+	std::array<uint8_t, 32> psk;
+	os_memcpy(psk.data(), wpa_ssid->psk, psk.size());
+	return {{SupplicantStatusCode::SUCCESS, ""}, psk};
+}
+
+std::pair<SupplicantStatus, std::vector<uint8_t>> StaNetwork::getWepKeyInternal(
+    uint32_t key_idx)
+{
+	std::vector<uint8_t> wep_key;
+	struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
+	if (key_idx >=
+	    static_cast<uint32_t>(
+		ISupplicantStaNetwork::ParamSizeLimits::WEP_KEYS_MAX_NUM)) {
+		return {{SupplicantStatusCode::FAILURE_ARGS_INVALID, ""},
+			wep_key};
+	}
+	wep_key.assign(
+	    wpa_ssid->wep_key[key_idx],
+	    wpa_ssid->wep_key[key_idx] + wpa_ssid->wep_key_len[key_idx]);
+	return {{SupplicantStatusCode::SUCCESS, ""}, std::move(wep_key)};
+}
+
+std::pair<SupplicantStatus, uint32_t> StaNetwork::getWepTxKeyIdxInternal()
+{
+	struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
+	return {{SupplicantStatusCode::SUCCESS, ""}, wpa_ssid->wep_tx_keyidx};
+}
+
+std::pair<SupplicantStatus, bool> StaNetwork::getRequirePmfInternal()
+{
+	struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
+	return {{SupplicantStatusCode::SUCCESS, ""},
+		(wpa_ssid->ieee80211w == MGMT_FRAME_PROTECTION_REQUIRED)};
+}
+
+std::pair<SupplicantStatus, ISupplicantStaNetwork::EapMethod>
+StaNetwork::getEapMethodInternal()
+{
+	struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
+	if (!wpa_ssid->eap.eap_methods) {
+		return {{SupplicantStatusCode::FAILURE_UNKNOWN, ""}, {}};
+	}
+	// wpa_supplicant can support setting multiple eap methods for each
+	// network. But, this is not really used by Android. So, just reading
+	// the first EAP method for each network.
+	const std::string eap_method_str = eap_get_name(
+	    wpa_ssid->eap.eap_methods[0].vendor,
+	    static_cast<EapType>(wpa_ssid->eap.eap_methods[0].method));
+	size_t eap_method_idx =
+	    std::find(
+		std::begin(kEapMethodStrings), std::end(kEapMethodStrings),
+		eap_method_str) -
+	    std::begin(kEapMethodStrings);
+	if (eap_method_idx >= kEapMethodMax) {
+		return {{SupplicantStatusCode::FAILURE_UNKNOWN, ""}, {}};
+	}
+	return {{SupplicantStatusCode::SUCCESS, ""},
+		static_cast<ISupplicantStaNetwork::EapMethod>(eap_method_idx)};
+}
+
+std::pair<SupplicantStatus, ISupplicantStaNetwork::EapPhase2Method>
+StaNetwork::getEapPhase2MethodInternal()
+{
+	struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
+	if (!wpa_ssid->eap.phase2) {
+		return {{SupplicantStatusCode::FAILURE_UNKNOWN, ""}, {}};
+	}
+	const std::string eap_phase2_method_str_with_prefix =
+	    wpa_ssid->eap.phase2;
+	std::string eap_phase2_method_str;
+	// Strip out the phase 2 method prefix before doing a reverse lookup
+	// of phase 2 string to the Eap Phase 2 type.
+	if (eap_phase2_method_str_with_prefix.find(kEapPhase2AuthPrefix) == 0) {
+		eap_phase2_method_str =
+		    eap_phase2_method_str_with_prefix.substr(
+			strlen(kEapPhase2AuthPrefix),
+			eap_phase2_method_str_with_prefix.size());
+	} else if (
+	    eap_phase2_method_str_with_prefix.find(kEapPhase2AuthEapPrefix) ==
+	    0) {
+		eap_phase2_method_str =
+		    eap_phase2_method_str_with_prefix.substr(
+			strlen(kEapPhase2AuthEapPrefix),
+			eap_phase2_method_str_with_prefix.size());
+	}
+	size_t eap_phase2_method_idx =
+	    std::find(
+		std::begin(kEapPhase2MethodStrings),
+		std::end(kEapPhase2MethodStrings), eap_phase2_method_str) -
+	    std::begin(kEapPhase2MethodStrings);
+	if (eap_phase2_method_idx >= kEapPhase2MethodMax) {
+		return {{SupplicantStatusCode::FAILURE_UNKNOWN, ""}, {}};
+	}
+	return {{SupplicantStatusCode::SUCCESS, ""},
+		static_cast<ISupplicantStaNetwork::EapPhase2Method>(
+		    eap_phase2_method_idx)};
+}
+
+std::pair<SupplicantStatus, std::vector<uint8_t>>
+StaNetwork::getEapIdentityInternal()
+{
+	struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
+	if (!wpa_ssid->eap.identity) {
+		return {{SupplicantStatusCode::FAILURE_UNKNOWN, ""}, {}};
+	}
+	return {{SupplicantStatusCode::SUCCESS, ""},
+		std::vector<uint8_t>(
+		    wpa_ssid->eap.identity,
+		    wpa_ssid->eap.identity + wpa_ssid->eap.identity_len)};
+}
+
+std::pair<SupplicantStatus, std::vector<uint8_t>>
+StaNetwork::getEapAnonymousIdentityInternal()
+{
+	struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
+	if (!wpa_ssid->eap.anonymous_identity) {
+		return {{SupplicantStatusCode::FAILURE_UNKNOWN, ""}, {}};
+	}
+	return {{SupplicantStatusCode::SUCCESS, ""},
+		std::vector<uint8_t>(
+		    wpa_ssid->eap.anonymous_identity,
+		    wpa_ssid->eap.anonymous_identity +
+			wpa_ssid->eap.anonymous_identity_len)};
+}
+
+std::pair<SupplicantStatus, std::vector<uint8_t>>
+StaNetwork::getEapPasswordInternal()
+{
+	struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
+	if (!wpa_ssid->eap.password) {
+		return {{SupplicantStatusCode::FAILURE_UNKNOWN, ""}, {}};
+	}
+	return {{SupplicantStatusCode::SUCCESS, ""},
+		std::vector<uint8_t>(
+		    wpa_ssid->eap.password,
+		    wpa_ssid->eap.password + wpa_ssid->eap.password_len)};
+}
+
+std::pair<SupplicantStatus, std::string> StaNetwork::getEapCACertInternal()
+{
+	struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
+	if (!wpa_ssid->eap.ca_cert) {
+		return {{SupplicantStatusCode::FAILURE_UNKNOWN, ""}, {}};
+	}
+	return {{SupplicantStatusCode::SUCCESS, ""},
+		reinterpret_cast<char *>(wpa_ssid->eap.ca_cert)};
+}
+
+std::pair<SupplicantStatus, std::string> StaNetwork::getEapCAPathInternal()
+{
+	struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
+	if (!wpa_ssid->eap.ca_path) {
+		return {{SupplicantStatusCode::FAILURE_UNKNOWN, ""}, {}};
+	}
+	return {{SupplicantStatusCode::SUCCESS, ""},
+		reinterpret_cast<char *>(wpa_ssid->eap.ca_path)};
+}
+
+std::pair<SupplicantStatus, std::string> StaNetwork::getEapClientCertInternal()
+{
+	struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
+	if (!wpa_ssid->eap.client_cert) {
+		return {{SupplicantStatusCode::FAILURE_UNKNOWN, ""}, {}};
+	}
+	return {{SupplicantStatusCode::SUCCESS, ""},
+		reinterpret_cast<char *>(wpa_ssid->eap.client_cert)};
+}
+
+std::pair<SupplicantStatus, std::string>
+StaNetwork::getEapPrivateKeyIdInternal()
+{
+	struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
+	if (!wpa_ssid->eap.key_id) {
+		return {{SupplicantStatusCode::FAILURE_UNKNOWN, ""}, {}};
+	}
+	return {{SupplicantStatusCode::SUCCESS, ""}, wpa_ssid->eap.key_id};
+}
+
+std::pair<SupplicantStatus, std::string>
+StaNetwork::getEapSubjectMatchInternal()
+{
+	struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
+	if (!wpa_ssid->eap.subject_match) {
+		return {{SupplicantStatusCode::FAILURE_UNKNOWN, ""}, {}};
+	}
+	return {{SupplicantStatusCode::SUCCESS, ""},
+		reinterpret_cast<char *>(wpa_ssid->eap.subject_match)};
+}
+
+std::pair<SupplicantStatus, std::string>
+StaNetwork::getEapAltSubjectMatchInternal()
+{
+	struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
+	if (!wpa_ssid->eap.altsubject_match) {
+		return {{SupplicantStatusCode::FAILURE_UNKNOWN, ""}, {}};
+	}
+	return {{SupplicantStatusCode::SUCCESS, ""},
+		reinterpret_cast<char *>(wpa_ssid->eap.altsubject_match)};
+}
+
+std::pair<SupplicantStatus, bool> StaNetwork::getEapEngineInternal()
+{
+	struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
+	return {{SupplicantStatusCode::SUCCESS, ""}, wpa_ssid->eap.engine == 1};
+}
+
+std::pair<SupplicantStatus, std::string> StaNetwork::getEapEngineIDInternal()
+{
+	struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
+	if (!wpa_ssid->eap.engine_id) {
+		return {{SupplicantStatusCode::FAILURE_UNKNOWN, ""}, {}};
+	}
+	return {{SupplicantStatusCode::SUCCESS, ""}, {wpa_ssid->eap.engine_id}};
+}
+
+std::pair<SupplicantStatus, std::string>
+StaNetwork::getEapDomainSuffixMatchInternal()
+{
+	struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
+	if (!wpa_ssid->eap.domain_suffix_match) {
+		return {{SupplicantStatusCode::FAILURE_UNKNOWN, ""}, {}};
+	}
+	return {{SupplicantStatusCode::SUCCESS, ""},
+		{wpa_ssid->eap.domain_suffix_match}};
+}
+
+std::pair<SupplicantStatus, std::string> StaNetwork::getIdStrInternal()
+{
+	struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
+	if (!wpa_ssid->id_str) {
+		return {{SupplicantStatusCode::FAILURE_UNKNOWN, ""}, {}};
+	}
+	return {{SupplicantStatusCode::SUCCESS, ""}, {wpa_ssid->id_str}};
+}
+
+std::pair<SupplicantStatus, std::vector<uint8_t>>
+StaNetwork::getWpsNfcConfigurationTokenInternal()
+{
+	struct wpa_supplicant *wpa_s = retrieveIfacePtr();
+	struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
+	auto token_buf = misc_utils::createWpaBufUniquePtr(
+	    wpas_wps_network_config_token(wpa_s, 0, wpa_ssid));
+	if (!token_buf) {
+		return {{SupplicantStatusCode::FAILURE_UNKNOWN, ""}, {}};
+	}
+	return {{SupplicantStatusCode::SUCCESS, ""},
+		misc_utils::convertWpaBufToVector(token_buf.get())};
+}
+
+SupplicantStatus StaNetwork::enableInternal(bool no_connect)
+{
+	struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
+	if (wpa_ssid->disabled == 2) {
+		return {SupplicantStatusCode::FAILURE_UNKNOWN, ""};
+	}
+	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 {SupplicantStatusCode::SUCCESS, ""};
+}
+
+SupplicantStatus StaNetwork::disableInternal()
+{
+	struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
+	if (wpa_ssid->disabled == 2) {
+		return {SupplicantStatusCode::FAILURE_UNKNOWN, ""};
+	}
+	struct wpa_supplicant *wpa_s = retrieveIfacePtr();
+	wpa_supplicant_disable_network(wpa_s, wpa_ssid);
+	return {SupplicantStatusCode::SUCCESS, ""};
+}
+
+SupplicantStatus StaNetwork::selectInternal()
+{
+	struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
+	if (wpa_ssid->disabled == 2) {
+		return {SupplicantStatusCode::FAILURE_UNKNOWN, ""};
+	}
+	struct wpa_supplicant *wpa_s = retrieveIfacePtr();
+	wpa_s->scan_min_time.sec = 0;
+	wpa_s->scan_min_time.usec = 0;
+	// Make sure that the supplicant is updated to the latest
+	// MAC address, which might have changed due to MAC randomization.
+	wpa_supplicant_update_mac_addr(wpa_s);
+	wpa_supplicant_select_network(wpa_s, wpa_ssid);
+	return {SupplicantStatusCode::SUCCESS, ""};
+}
+
+SupplicantStatus StaNetwork::sendNetworkEapSimGsmAuthResponseInternal(
+    const std::vector<ISupplicantStaNetwork::NetworkResponseEapSimGsmAuthParams>
+	&vec_params)
+{
+	struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
+	// Convert the incoming parameters to a string to pass to
+	// wpa_supplicant.
+	std::string ctrl_rsp_param = std::string(kNetworkEapSimGsmAuthResponse);
+	for (const auto &params : vec_params) {
+		uint32_t kc_hex_len = params.kc.size() * 2 + 1;
+		std::vector<char> kc_hex(kc_hex_len);
+		uint32_t sres_hex_len = params.sres.size() * 2 + 1;
+		std::vector<char> sres_hex(sres_hex_len);
+		wpa_snprintf_hex(
+		    kc_hex.data(), kc_hex.size(), params.kc.data(),
+		    params.kc.size());
+		wpa_snprintf_hex(
+		    sres_hex.data(), sres_hex.size(), params.sres.data(),
+		    params.sres.size());
+		ctrl_rsp_param += ":" + std::string(kc_hex.data()) + ":" +
+				  std::string(sres_hex.data());
+	}
+	enum wpa_ctrl_req_type rtype = WPA_CTRL_REQ_SIM;
+	struct wpa_supplicant *wpa_s = retrieveIfacePtr();
+	if (wpa_supplicant_ctrl_rsp_handle(
+		wpa_s, wpa_ssid, rtype, ctrl_rsp_param.c_str(),
+		ctrl_rsp_param.size())) {
+		return {SupplicantStatusCode::FAILURE_UNKNOWN, ""};
+	}
+	eapol_sm_notify_ctrl_response(wpa_s->eapol);
+	wpa_hexdump_ascii_key(
+	    MSG_DEBUG, "network sim gsm auth response param",
+	    (const u8 *)ctrl_rsp_param.c_str(), ctrl_rsp_param.size());
+	return {SupplicantStatusCode::SUCCESS, ""};
+}
+
+SupplicantStatus StaNetwork::sendNetworkEapSimGsmAuthFailureInternal()
+{
+	struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
+	struct wpa_supplicant *wpa_s = retrieveIfacePtr();
+	enum wpa_ctrl_req_type rtype = WPA_CTRL_REQ_SIM;
+	if (wpa_supplicant_ctrl_rsp_handle(
+		wpa_s, wpa_ssid, rtype, kNetworkEapSimGsmAuthFailure,
+		strlen(kNetworkEapSimGsmAuthFailure))) {
+		return {SupplicantStatusCode::FAILURE_UNKNOWN, ""};
+	}
+	eapol_sm_notify_ctrl_response(wpa_s->eapol);
+	return {SupplicantStatusCode::SUCCESS, ""};
+}
+
+SupplicantStatus StaNetwork::sendNetworkEapSimUmtsAuthResponseInternal(
+    const ISupplicantStaNetwork::NetworkResponseEapSimUmtsAuthParams &params)
+{
+	struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
+	// Convert the incoming parameters to a string to pass to
+	// wpa_supplicant.
+	uint32_t ik_hex_len = params.ik.size() * 2 + 1;
+	std::vector<char> ik_hex(ik_hex_len);
+	uint32_t ck_hex_len = params.ck.size() * 2 + 1;
+	std::vector<char> ck_hex(ck_hex_len);
+	uint32_t res_hex_len = params.res.size() * 2 + 1;
+	std::vector<char> res_hex(res_hex_len);
+	wpa_snprintf_hex(
+	    ik_hex.data(), ik_hex.size(), params.ik.data(), params.ik.size());
+	wpa_snprintf_hex(
+	    ck_hex.data(), ck_hex.size(), params.ck.data(), params.ck.size());
+	wpa_snprintf_hex(
+	    res_hex.data(), res_hex.size(), params.res.data(),
+	    params.res.size());
+	std::string ctrl_rsp_param =
+	    std::string(kNetworkEapSimUmtsAuthResponse) + ":" +
+	    std::string(ik_hex.data()) + ":" + std::string(ck_hex.data()) +
+	    ":" + std::string(res_hex.data());
+	enum wpa_ctrl_req_type rtype = WPA_CTRL_REQ_SIM;
+	struct wpa_supplicant *wpa_s = retrieveIfacePtr();
+	if (wpa_supplicant_ctrl_rsp_handle(
+		wpa_s, wpa_ssid, rtype, ctrl_rsp_param.c_str(),
+		ctrl_rsp_param.size())) {
+		return {SupplicantStatusCode::FAILURE_UNKNOWN, ""};
+	}
+	eapol_sm_notify_ctrl_response(wpa_s->eapol);
+	wpa_hexdump_ascii_key(
+	    MSG_DEBUG, "network sim umts auth response param",
+	    (const u8 *)ctrl_rsp_param.c_str(), ctrl_rsp_param.size());
+	return {SupplicantStatusCode::SUCCESS, ""};
+}
+
+SupplicantStatus StaNetwork::sendNetworkEapSimUmtsAutsResponseInternal(
+    const std::array<uint8_t, 14> &auts)
+{
+	struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
+	uint32_t auts_hex_len = auts.size() * 2 + 1;
+	std::vector<char> auts_hex(auts_hex_len);
+	wpa_snprintf_hex(
+	    auts_hex.data(), auts_hex.size(), auts.data(), auts.size());
+	std::string ctrl_rsp_param =
+	    std::string(kNetworkEapSimUmtsAutsResponse) + ":" +
+	    std::string(auts_hex.data());
+	enum wpa_ctrl_req_type rtype = WPA_CTRL_REQ_SIM;
+	struct wpa_supplicant *wpa_s = retrieveIfacePtr();
+	if (wpa_supplicant_ctrl_rsp_handle(
+		wpa_s, wpa_ssid, rtype, ctrl_rsp_param.c_str(),
+		ctrl_rsp_param.size())) {
+		return {SupplicantStatusCode::FAILURE_UNKNOWN, ""};
+	}
+	eapol_sm_notify_ctrl_response(wpa_s->eapol);
+	wpa_hexdump_ascii_key(
+	    MSG_DEBUG, "network sim umts auts response param",
+	    (const u8 *)ctrl_rsp_param.c_str(), ctrl_rsp_param.size());
+	return {SupplicantStatusCode::SUCCESS, ""};
+}
+
+SupplicantStatus StaNetwork::sendNetworkEapSimUmtsAuthFailureInternal()
+{
+	struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
+	struct wpa_supplicant *wpa_s = retrieveIfacePtr();
+	enum wpa_ctrl_req_type rtype = WPA_CTRL_REQ_SIM;
+	if (wpa_supplicant_ctrl_rsp_handle(
+		wpa_s, wpa_ssid, rtype, kNetworkEapSimUmtsAuthFailure,
+		strlen(kNetworkEapSimUmtsAuthFailure))) {
+		return {SupplicantStatusCode::FAILURE_UNKNOWN, ""};
+	}
+	eapol_sm_notify_ctrl_response(wpa_s->eapol);
+	return {SupplicantStatusCode::SUCCESS, ""};
+}
+
+SupplicantStatus StaNetwork::sendNetworkEapIdentityResponseInternal(
+    const std::vector<uint8_t> &identity)
+{
+	struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
+	std::string ctrl_rsp_param(identity.begin(), identity.end());
+	enum wpa_ctrl_req_type rtype = WPA_CTRL_REQ_EAP_IDENTITY;
+	struct wpa_supplicant *wpa_s = retrieveIfacePtr();
+	if (wpa_supplicant_ctrl_rsp_handle(
+		wpa_s, wpa_ssid, rtype, ctrl_rsp_param.c_str(),
+		ctrl_rsp_param.size())) {
+		return {SupplicantStatusCode::FAILURE_UNKNOWN, ""};
+	}
+	eapol_sm_notify_ctrl_response(wpa_s->eapol);
+	wpa_hexdump_ascii_key(
+	    MSG_DEBUG, "network identity response param",
+	    (const u8 *)ctrl_rsp_param.c_str(), ctrl_rsp_param.size());
+	return {SupplicantStatusCode::SUCCESS, ""};
+}
+
+SupplicantStatus StaNetwork::sendNetworkEapIdentityResponseInternal_1_1(
+    const std::vector<uint8_t> &identity, const std::vector<uint8_t> &encrypted_imsi_identity)
+{
+	struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
+	// format: plain identity + ":" + encrypted identity(encrypted_imsi_identity)
+	std::string ctrl_rsp_param =
+		std::string(identity.begin(), identity.end()) + ":" +
+		std::string(encrypted_imsi_identity.begin(), encrypted_imsi_identity.end());
+	enum wpa_ctrl_req_type rtype = WPA_CTRL_REQ_EAP_IDENTITY;
+	struct wpa_supplicant *wpa_s = retrieveIfacePtr();
+	if (wpa_supplicant_ctrl_rsp_handle(
+		wpa_s, wpa_ssid, rtype, ctrl_rsp_param.c_str(),
+		ctrl_rsp_param.size())) {
+		return {SupplicantStatusCode::FAILURE_UNKNOWN, ""};
+	}
+	eapol_sm_notify_ctrl_response(wpa_s->eapol);
+	wpa_hexdump_ascii_key(
+	    MSG_DEBUG, "network identity response param",
+	    (const u8 *)ctrl_rsp_param.c_str(), ctrl_rsp_param.size());
+	return {SupplicantStatusCode::SUCCESS, ""};
+}
+
+/**
+ * Retrieve the underlying |wpa_ssid| struct pointer for
+ * this network.
+ * If the underlying network is removed or the interface
+ * this network belong to
+ * is removed, all RPC method calls on this object will
+ * return failure.
+ */
+struct wpa_ssid *StaNetwork::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 *StaNetwork::retrieveIfacePtr()
+{
+	return wpa_supplicant_get_iface(wpa_global_, ifname_.c_str());
+}
+
+/**
+ * Check if the provided psk passhrase is valid or not.
+ *
+ * Returns 0 if valid, 1 otherwise.
+ */
+int StaNetwork::isPskPassphraseValid(const std::string &psk)
+{
+	if (psk.size() <
+		static_cast<uint32_t>(ISupplicantStaNetwork::ParamSizeLimits::
+					  PSK_PASSPHRASE_MIN_LEN_IN_BYTES) ||
+	    psk.size() >
+		static_cast<uint32_t>(ISupplicantStaNetwork::ParamSizeLimits::
+					  PSK_PASSPHRASE_MAX_LEN_IN_BYTES)) {
+		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 StaNetwork::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.
+ */
+int StaNetwork::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.
+ */
+int StaNetwork::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 1;
+	}
+	wpa_hexdump_ascii(
+	    MSG_MSGDUMP, hexdump_prefix, *to_update_field, value_len);
+	resetInternalStateAfterParamsUpdate();
+	return 0;
+}
+
+/**
+ * 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.
+ */
+int StaNetwork::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 1;
+	}
+	wpa_hexdump_ascii_key(
+	    MSG_MSGDUMP, hexdump_prefix, *to_update_field, value_len);
+	resetInternalStateAfterParamsUpdate();
+	return 0;
+}
+
+/**
+ * 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.
+ */
+int StaNetwork::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 1;
+	}
+	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 0;
+}
+
+/**
+ * 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.
+ */
+int StaNetwork::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 1;
+	}
+	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 0;
+}
+
+}  // namespace implementation
+}  // namespace V1_1
+}  // namespace wifi
+}  // namespace supplicant
+}  // namespace hardware
+}  // namespace android
diff --git a/wpa_supplicant/hidl/1.1/sta_network.h b/wpa_supplicant/hidl/1.1/sta_network.h
new file mode 100644
index 0000000..b647773
--- /dev/null
+++ b/wpa_supplicant/hidl/1.1/sta_network.h
@@ -0,0 +1,344 @@
+/*
+ * 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_STA_NETWORK_H
+#define WPA_SUPPLICANT_HIDL_STA_NETWORK_H
+
+#include <array>
+#include <vector>
+
+#include <android-base/macros.h>
+
+#include <android/hardware/wifi/supplicant/1.1/ISupplicantStaNetwork.h>
+#include <android/hardware/wifi/supplicant/1.0/ISupplicantStaNetworkCallback.h>
+
+extern "C" {
+#include "utils/common.h"
+#include "utils/includes.h"
+#include "config.h"
+#include "wpa_supplicant_i.h"
+#include "notify.h"
+#include "eapol_supp/eapol_supp_sm.h"
+#include "eap_peer/eap.h"
+#include "rsn_supp/wpa.h"
+}
+
+namespace android {
+namespace hardware {
+namespace wifi {
+namespace supplicant {
+namespace V1_1 {
+namespace implementation {
+using namespace android::hardware::wifi::supplicant::V1_0;
+
+/**
+ * Implementation of StaNetwork hidl object. Each unique hidl
+ * object is used for control operations on a specific network
+ * controlled by wpa_supplicant.
+ */
+class StaNetwork : public V1_1::ISupplicantStaNetwork
+{
+public:
+	StaNetwork(
+	    struct wpa_global* wpa_global, const char ifname[], int network_id);
+	~StaNetwork() override = default;
+	// Refer to |StaIface::invalidate()|.
+	void invalidate();
+	bool isValid();
+
+	// Hidl methods exposed.
+	Return<void> getId(getId_cb _hidl_cb) override;
+	Return<void> getInterfaceName(getInterfaceName_cb _hidl_cb) override;
+	Return<void> getType(getType_cb _hidl_cb) override;
+	Return<void> registerCallback(
+	    const sp<ISupplicantStaNetworkCallback>& callback,
+	    registerCallback_cb _hidl_cb) override;
+	Return<void> setSsid(
+	    const hidl_vec<uint8_t>& ssid, setSsid_cb _hidl_cb) override;
+	Return<void> setBssid(
+	    const hidl_array<uint8_t, 6>& bssid, setBssid_cb _hidl_cb) override;
+	Return<void> setScanSsid(bool enable, setScanSsid_cb _hidl_cb) override;
+	Return<void> setKeyMgmt(
+	    uint32_t key_mgmt_mask, setKeyMgmt_cb _hidl_cb) override;
+	Return<void> setProto(
+	    uint32_t proto_mask, setProto_cb _hidl_cb) override;
+	Return<void> setAuthAlg(
+	    uint32_t auth_alg_mask, setAuthAlg_cb _hidl_cb) override;
+	Return<void> setGroupCipher(
+	    uint32_t group_cipher_mask, setGroupCipher_cb _hidl_cb) override;
+	Return<void> setPairwiseCipher(
+	    uint32_t pairwise_cipher_mask,
+	    setPairwiseCipher_cb _hidl_cb) override;
+	Return<void> setPskPassphrase(
+	    const hidl_string& psk, setPskPassphrase_cb _hidl_cb) override;
+	Return<void> setPsk(
+	    const hidl_array<uint8_t, 32>& psk, setPsk_cb _hidl_cb) override;
+	Return<void> setWepKey(
+	    uint32_t key_idx, const hidl_vec<uint8_t>& wep_key,
+	    setWepKey_cb _hidl_cb) override;
+	Return<void> setWepTxKeyIdx(
+	    uint32_t key_idx, setWepTxKeyIdx_cb _hidl_cb) override;
+	Return<void> setRequirePmf(
+	    bool enable, setRequirePmf_cb _hidl_cb) override;
+	Return<void> setEapMethod(
+	    ISupplicantStaNetwork::EapMethod method,
+	    setEapMethod_cb _hidl_cb) override;
+	Return<void> setEapPhase2Method(
+	    ISupplicantStaNetwork::EapPhase2Method method,
+	    setEapPhase2Method_cb _hidl_cb) override;
+	Return<void> setEapIdentity(
+	    const hidl_vec<uint8_t>& identity,
+	    setEapIdentity_cb _hidl_cb) override;
+	Return<void> setEapAnonymousIdentity(
+	    const hidl_vec<uint8_t>& identity,
+	    setEapAnonymousIdentity_cb _hidl_cb) override;
+	Return<void> setEapPassword(
+	    const hidl_vec<uint8_t>& password,
+	    setEapPassword_cb _hidl_cb) override;
+	Return<void> setEapCACert(
+	    const hidl_string& path, setEapCACert_cb _hidl_cb) override;
+	Return<void> setEapCAPath(
+	    const hidl_string& path, setEapCAPath_cb _hidl_cb) override;
+	Return<void> setEapClientCert(
+	    const hidl_string& path, setEapClientCert_cb _hidl_cb) override;
+	Return<void> setEapPrivateKeyId(
+	    const hidl_string& id, setEapPrivateKeyId_cb _hidl_cb) override;
+        Return<void> setEapEncryptedImsiIdentity(
+            const EapSimEncryptedIdentity& identity,
+            setEapEncryptedImsiIdentity_cb _hidl_cb) override;
+	Return<void> setEapSubjectMatch(
+	    const hidl_string& match, setEapSubjectMatch_cb _hidl_cb) override;
+	Return<void> setEapAltSubjectMatch(
+	    const hidl_string& match,
+	    setEapAltSubjectMatch_cb _hidl_cb) override;
+	Return<void> setEapEngine(
+	    bool enable, setEapEngine_cb _hidl_cb) override;
+	Return<void> setEapEngineID(
+	    const hidl_string& id, setEapEngineID_cb _hidl_cb) override;
+	Return<void> setEapDomainSuffixMatch(
+	    const hidl_string& match,
+	    setEapDomainSuffixMatch_cb _hidl_cb) override;
+	Return<void> setProactiveKeyCaching(
+	    bool enable, setProactiveKeyCaching_cb _hidl_cb) override;
+	Return<void> setIdStr(
+	    const hidl_string& id_str, setIdStr_cb _hidl_cb) override;
+	Return<void> setUpdateIdentifier(
+	    uint32_t id, setUpdateIdentifier_cb _hidl_cb) override;
+	Return<void> getSsid(getSsid_cb _hidl_cb) override;
+	Return<void> getBssid(getBssid_cb _hidl_cb) override;
+	Return<void> getScanSsid(getScanSsid_cb _hidl_cb) override;
+	Return<void> getKeyMgmt(getKeyMgmt_cb _hidl_cb) override;
+	Return<void> getProto(getProto_cb _hidl_cb) override;
+	Return<void> getAuthAlg(getAuthAlg_cb _hidl_cb) override;
+	Return<void> getGroupCipher(getGroupCipher_cb _hidl_cb) override;
+	Return<void> getPairwiseCipher(getPairwiseCipher_cb _hidl_cb) override;
+	Return<void> getPskPassphrase(getPskPassphrase_cb _hidl_cb) override;
+	Return<void> getPsk(getPsk_cb _hidl_cb) override;
+	Return<void> getWepKey(
+	    uint32_t key_idx, getWepKey_cb _hidl_cb) override;
+	Return<void> getWepTxKeyIdx(getWepTxKeyIdx_cb _hidl_cb) override;
+	Return<void> getRequirePmf(getRequirePmf_cb _hidl_cb) override;
+	Return<void> getEapMethod(getEapMethod_cb _hidl_cb) override;
+	Return<void> getEapPhase2Method(
+	    getEapPhase2Method_cb _hidl_cb) override;
+	Return<void> getEapIdentity(getEapIdentity_cb _hidl_cb) override;
+	Return<void> getEapAnonymousIdentity(
+	    getEapAnonymousIdentity_cb _hidl_cb) override;
+	Return<void> getEapPassword(getEapPassword_cb _hidl_cb) override;
+	Return<void> getEapCACert(getEapCACert_cb _hidl_cb) override;
+	Return<void> getEapCAPath(getEapCAPath_cb _hidl_cb) override;
+	Return<void> getEapClientCert(getEapClientCert_cb _hidl_cb) override;
+	Return<void> getEapPrivateKeyId(
+	    getEapPrivateKeyId_cb _hidl_cb) override;
+	Return<void> getEapSubjectMatch(
+	    getEapSubjectMatch_cb _hidl_cb) override;
+	Return<void> getEapAltSubjectMatch(
+	    getEapAltSubjectMatch_cb _hidl_cb) override;
+	Return<void> getEapEngine(getEapEngine_cb _hidl_cb) override;
+	Return<void> getEapEngineID(getEapEngineID_cb _hidl_cb) override;
+	Return<void> getEapDomainSuffixMatch(
+	    getEapDomainSuffixMatch_cb _hidl_cb) override;
+	Return<void> getIdStr(getIdStr_cb _hidl_cb) override;
+	Return<void> getWpsNfcConfigurationToken(
+	    getWpsNfcConfigurationToken_cb _hidl_cb) override;
+	Return<void> enable(bool no_connect, enable_cb _hidl_cb) override;
+	Return<void> disable(disable_cb _hidl_cb) override;
+	Return<void> select(select_cb _hidl_cb) override;
+	Return<void> sendNetworkEapSimGsmAuthResponse(
+	    const hidl_vec<
+		ISupplicantStaNetwork::NetworkResponseEapSimGsmAuthParams>&
+		vec_params,
+	    sendNetworkEapSimGsmAuthResponse_cb _hidl_cb) override;
+	Return<void> sendNetworkEapSimGsmAuthFailure(
+	    sendNetworkEapSimGsmAuthFailure_cb _hidl_cb) override;
+	Return<void> sendNetworkEapSimUmtsAuthResponse(
+	    const ISupplicantStaNetwork::NetworkResponseEapSimUmtsAuthParams&
+		params,
+	    sendNetworkEapSimUmtsAuthResponse_cb _hidl_cb) override;
+	Return<void> sendNetworkEapSimUmtsAutsResponse(
+	    const hidl_array<uint8_t, 14>& auts,
+	    sendNetworkEapSimUmtsAutsResponse_cb _hidl_cb) override;
+	Return<void> sendNetworkEapSimUmtsAuthFailure(
+	    sendNetworkEapSimUmtsAuthFailure_cb _hidl_cb) override;
+	Return<void> sendNetworkEapIdentityResponse(
+	    const hidl_vec<uint8_t>& identity,
+	    sendNetworkEapIdentityResponse_cb _hidl_cb) override;
+	Return<void> sendNetworkEapIdentityResponse_1_1(
+	    const EapSimIdentity& identity,
+	    const EapSimEncryptedIdentity& imsiIdentity,
+	    sendNetworkEapIdentityResponse_1_1_cb _hidl_cb) override;
+
+private:
+	// Corresponding worker functions for the HIDL methods.
+	std::pair<SupplicantStatus, uint32_t> getIdInternal();
+	std::pair<SupplicantStatus, std::string> getInterfaceNameInternal();
+	std::pair<SupplicantStatus, IfaceType> getTypeInternal();
+	SupplicantStatus registerCallbackInternal(
+	    const sp<ISupplicantStaNetworkCallback>& callback);
+	SupplicantStatus setSsidInternal(const std::vector<uint8_t>& ssid);
+	SupplicantStatus setBssidInternal(const std::array<uint8_t, 6>& bssid);
+	SupplicantStatus setScanSsidInternal(bool enable);
+	SupplicantStatus setKeyMgmtInternal(uint32_t key_mgmt_mask);
+	SupplicantStatus setProtoInternal(uint32_t proto_mask);
+	SupplicantStatus setAuthAlgInternal(uint32_t auth_alg_mask);
+	SupplicantStatus setGroupCipherInternal(uint32_t group_cipher_mask);
+	SupplicantStatus setPairwiseCipherInternal(
+	    uint32_t pairwise_cipher_mask);
+	SupplicantStatus setPskPassphraseInternal(const std::string& psk);
+	SupplicantStatus setPskInternal(const std::array<uint8_t, 32>& psk);
+	SupplicantStatus setWepKeyInternal(
+	    uint32_t key_idx, const std::vector<uint8_t>& wep_key);
+	SupplicantStatus setWepTxKeyIdxInternal(uint32_t key_idx);
+	SupplicantStatus setRequirePmfInternal(bool enable);
+	SupplicantStatus setEapMethodInternal(
+	    ISupplicantStaNetwork::EapMethod method);
+	SupplicantStatus setEapPhase2MethodInternal(
+	    ISupplicantStaNetwork::EapPhase2Method method);
+	SupplicantStatus setEapIdentityInternal(
+	    const std::vector<uint8_t>& identity);
+        SupplicantStatus setEapEncryptedImsiIdentityInternal(
+	    const std::vector<uint8_t>& identity);
+	SupplicantStatus setEapAnonymousIdentityInternal(
+	    const std::vector<uint8_t>& identity);
+	SupplicantStatus setEapPasswordInternal(
+	    const std::vector<uint8_t>& password);
+	SupplicantStatus setEapCACertInternal(const std::string& path);
+	SupplicantStatus setEapCAPathInternal(const std::string& path);
+	SupplicantStatus setEapClientCertInternal(const std::string& path);
+	SupplicantStatus setEapPrivateKeyIdInternal(const std::string& id);
+	SupplicantStatus setEapSubjectMatchInternal(const std::string& match);
+	SupplicantStatus setEapAltSubjectMatchInternal(
+	    const std::string& match);
+	SupplicantStatus setEapEngineInternal(bool enable);
+	SupplicantStatus setEapEngineIDInternal(const std::string& id);
+	SupplicantStatus setEapDomainSuffixMatchInternal(
+	    const std::string& match);
+	SupplicantStatus setProactiveKeyCachingInternal(bool enable);
+	SupplicantStatus setIdStrInternal(const std::string& id_str);
+	SupplicantStatus setUpdateIdentifierInternal(uint32_t id);
+	std::pair<SupplicantStatus, std::vector<uint8_t>> getSsidInternal();
+	std::pair<SupplicantStatus, std::array<uint8_t, 6>> getBssidInternal();
+	std::pair<SupplicantStatus, bool> getScanSsidInternal();
+	std::pair<SupplicantStatus, uint32_t> getKeyMgmtInternal();
+	std::pair<SupplicantStatus, uint32_t> getProtoInternal();
+	std::pair<SupplicantStatus, uint32_t> getAuthAlgInternal();
+	std::pair<SupplicantStatus, uint32_t> getGroupCipherInternal();
+	std::pair<SupplicantStatus, uint32_t> getPairwiseCipherInternal();
+	std::pair<SupplicantStatus, std::string> getPskPassphraseInternal();
+	std::pair<SupplicantStatus, std::array<uint8_t, 32>> getPskInternal();
+	std::pair<SupplicantStatus, std::vector<uint8_t>> getWepKeyInternal(
+	    uint32_t key_idx);
+	std::pair<SupplicantStatus, uint32_t> getWepTxKeyIdxInternal();
+	std::pair<SupplicantStatus, bool> getRequirePmfInternal();
+	std::pair<SupplicantStatus, ISupplicantStaNetwork::EapMethod>
+	getEapMethodInternal();
+	std::pair<SupplicantStatus, ISupplicantStaNetwork::EapPhase2Method>
+	getEapPhase2MethodInternal();
+	std::pair<SupplicantStatus, std::vector<uint8_t>>
+	getEapIdentityInternal();
+	std::pair<SupplicantStatus, std::vector<uint8_t>>
+	getEapAnonymousIdentityInternal();
+	std::pair<SupplicantStatus, std::vector<uint8_t>>
+	getEapPasswordInternal();
+	std::pair<SupplicantStatus, std::string> getEapCACertInternal();
+	std::pair<SupplicantStatus, std::string> getEapCAPathInternal();
+	std::pair<SupplicantStatus, std::string> getEapClientCertInternal();
+	std::pair<SupplicantStatus, std::string> getEapPrivateKeyIdInternal();
+	std::pair<SupplicantStatus, std::string> getEapSubjectMatchInternal();
+	std::pair<SupplicantStatus, std::string>
+	getEapAltSubjectMatchInternal();
+	std::pair<SupplicantStatus, bool> getEapEngineInternal();
+	std::pair<SupplicantStatus, std::string> getEapEngineIDInternal();
+	std::pair<SupplicantStatus, std::string>
+	getEapDomainSuffixMatchInternal();
+	std::pair<SupplicantStatus, std::string> getIdStrInternal();
+	std::pair<SupplicantStatus, std::vector<uint8_t>>
+	getWpsNfcConfigurationTokenInternal();
+	SupplicantStatus enableInternal(bool no_connect);
+	SupplicantStatus disableInternal();
+	SupplicantStatus selectInternal();
+	SupplicantStatus sendNetworkEapSimGsmAuthResponseInternal(
+	    const std::vector<
+		ISupplicantStaNetwork::NetworkResponseEapSimGsmAuthParams>&
+		vec_params);
+	SupplicantStatus sendNetworkEapSimGsmAuthFailureInternal();
+	SupplicantStatus sendNetworkEapSimUmtsAuthResponseInternal(
+	    const ISupplicantStaNetwork::NetworkResponseEapSimUmtsAuthParams&
+		params);
+	SupplicantStatus sendNetworkEapSimUmtsAutsResponseInternal(
+	    const std::array<uint8_t, 14>& auts);
+	SupplicantStatus sendNetworkEapSimUmtsAuthFailureInternal();
+	SupplicantStatus sendNetworkEapIdentityResponseInternal(
+	    const std::vector<uint8_t>& identity);
+	SupplicantStatus sendNetworkEapIdentityResponseInternal_1_1(
+	    const std::vector<uint8_t>& identity,
+	    const std::vector<uint8_t>& imsi_identity);
+
+	struct wpa_ssid* retrieveNetworkPtr();
+	struct wpa_supplicant* retrieveIfacePtr();
+	int isPskPassphraseValid(const std::string& psk);
+	void resetInternalStateAfterParamsUpdate();
+	int setStringFieldAndResetState(
+	    const char* value, uint8_t** to_update_field,
+	    const char* hexdump_prefix);
+	int setStringFieldAndResetState(
+	    const char* value, char** to_update_field,
+	    const char* hexdump_prefix);
+	int setStringKeyFieldAndResetState(
+	    const char* value, char** to_update_field,
+	    const char* hexdump_prefix);
+	int 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);
+	int 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.
+	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_;
+	bool is_valid_;
+
+	DISALLOW_COPY_AND_ASSIGN(StaNetwork);
+};
+
+}  // namespace implementation
+}  // namespace V1_1
+}  // namespace wifi
+}  // namespace supplicant
+}  // namespace hardware
+}  // namespace android
+
+#endif  // WPA_SUPPLICANT_HIDL_STA_NETWORK_H
diff --git a/wpa_supplicant/hidl/1.1/supplicant.cpp b/wpa_supplicant/hidl/1.1/supplicant.cpp
new file mode 100644
index 0000000..4785c37
--- /dev/null
+++ b/wpa_supplicant/hidl/1.1/supplicant.cpp
@@ -0,0 +1,423 @@
+/*
+ * hidl interface for wpa_supplicant daemon
+ * Copyright (c) 2004-2016, Jouni Malinen <j@w1.fi>
+ * Copyright (c) 2004-2016, Roshan Pius <rpius@google.com>
+ *
+ * This software may be distributed under the terms of the BSD license.
+ * See README for more details.
+ */
+
+#include "hidl_manager.h"
+#include "hidl_return_util.h"
+#include "supplicant.h"
+
+#include <android-base/file.h>
+#include <fcntl.h>
+#include <sys/stat.h>
+
+namespace {
+// Pre-populated interface params for interfaces controlled by wpa_supplicant.
+// Note: This may differ for other OEM's. So, modify this accordingly.
+constexpr char kIfaceDriverName[] = "nl80211";
+constexpr char kStaIfaceConfPath[] =
+    "/data/vendor/wifi/wpa/wpa_supplicant.conf";
+constexpr char kStaIfaceConfOverlayPath[] =
+    "/vendor/etc/wifi/wpa_supplicant_overlay.conf";
+constexpr char kP2pIfaceConfPath[] =
+    "/data/vendor/wifi/wpa/p2p_supplicant.conf";
+constexpr char kP2pIfaceConfOverlayPath[] =
+    "/vendor/etc/wifi/p2p_supplicant_overlay.conf";
+// Migrate conf files for existing devices.
+constexpr char kSystemTemplateConfPath[] =
+    "/system/etc/wifi/wpa_supplicant.conf";
+constexpr char kVendorTemplateConfPath[] =
+    "/vendor/etc/wifi/wpa_supplicant.conf";
+constexpr char kOldStaIfaceConfPath[] =
+    "/data/misc/wifi/wpa_supplicant.conf";
+constexpr char kOldP2pIfaceConfPath[] =
+    "/data/misc/wifi/p2p_supplicant.conf";
+constexpr mode_t kConfigFileMode = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP;
+
+int copyFile(
+    const std::string& src_file_path, const std::string& dest_file_path)
+{
+	std::string file_contents;
+	if (!android::base::ReadFileToString(src_file_path, &file_contents)) {
+		wpa_printf(
+		    MSG_ERROR, "Failed to read from %s. Errno: %s",
+		    src_file_path.c_str(), strerror(errno));
+		return -1;
+	}
+	if (!android::base::WriteStringToFile(
+		file_contents, dest_file_path, kConfigFileMode, getuid(),
+		getgid())) {
+		wpa_printf(
+		    MSG_ERROR, "Failed to write to %s. Errno: %s",
+		    dest_file_path.c_str(), strerror(errno));
+		return -1;
+	}
+	return 0;
+}
+
+/**
+ * Copy |src_file_path| to |dest_file_path| if it exists.
+ *
+ * Returns 1 if |src_file_path| does not exist or not accessible,
+ * Returns -1 if the copy fails.
+ * Returns 0 if the copy succeeds.
+ */
+int copyFileIfItExists(
+    const std::string& src_file_path, const std::string& dest_file_path)
+{
+	int ret = access(src_file_path.c_str(), R_OK);
+	// Sepolicy denial (2018+ device) will return EACCESS instead of ENOENT.
+	if ((ret != 0) && ((errno == ENOENT) || (errno == EACCES))) {
+		return 1;
+	}
+	ret = copyFile(src_file_path, dest_file_path);
+	if (ret != 0) {
+		wpa_printf(
+		    MSG_ERROR, "Failed copying %s to %s.",
+		    src_file_path.c_str(), dest_file_path.c_str());
+		return -1;
+	}
+	return 0;
+}
+
+/**
+ * Ensure that the specified config file pointed by |config_file_path| exists.
+ * a) If the |config_file_path| exists with the correct permissions, return.
+ * b) If the |config_file_path| does not exist, but |old_config_file_path|
+ * exists, copy over the contents of the |old_config_file_path| to
+ * |config_file_path|.
+ * c) If the |config_file_path| & |old_config_file_path|
+ * does not exists, copy over the contents of |template_config_file_path|.
+ */
+int ensureConfigFileExists(
+    const std::string& config_file_path,
+    const std::string& old_config_file_path)
+{
+	int ret = access(config_file_path.c_str(), R_OK | W_OK);
+	if (ret == 0) {
+		return 0;
+	}
+	if (errno == EACCES) {
+		ret = chmod(config_file_path.c_str(), kConfigFileMode);
+		if (ret == 0) {
+			return 0;
+		} else {
+			wpa_printf(
+			    MSG_ERROR, "Cannot set RW to %s. Errno: %s",
+			    config_file_path.c_str(), strerror(errno));
+			return -1;
+		}
+	} else if (errno != ENOENT) {
+		wpa_printf(
+		    MSG_ERROR, "Cannot acces %s. Errno: %s",
+		    config_file_path.c_str(), strerror(errno));
+		return -1;
+	}
+	ret = copyFileIfItExists(old_config_file_path, config_file_path);
+	if (ret == 0) {
+		wpa_printf(
+		    MSG_INFO, "Migrated conf file from %s to %s",
+		    old_config_file_path.c_str(), config_file_path.c_str());
+		unlink(old_config_file_path.c_str());
+		return 0;
+	} else if (ret == -1) {
+		unlink(config_file_path.c_str());
+		return -1;
+	}
+	ret = copyFileIfItExists(kVendorTemplateConfPath, config_file_path);
+	if (ret == 0) {
+		wpa_printf(
+		    MSG_INFO, "Copied template conf file from %s to %s",
+		    kVendorTemplateConfPath, config_file_path.c_str());
+		return 0;
+	} else if (ret == -1) {
+		unlink(config_file_path.c_str());
+		return -1;
+	}
+	ret = copyFileIfItExists(kSystemTemplateConfPath, config_file_path);
+	if (ret == 0) {
+		wpa_printf(
+		    MSG_INFO, "Copied template conf file from %s to %s",
+		    kSystemTemplateConfPath, config_file_path.c_str());
+		return 0;
+	} else if (ret == -1) {
+		unlink(config_file_path.c_str());
+		return -1;
+	}
+	// Did not create the conf file.
+	return -1;
+}
+}  // namespace
+
+namespace android {
+namespace hardware {
+namespace wifi {
+namespace supplicant {
+namespace V1_1 {
+namespace implementation {
+using hidl_return_util::validateAndCall;
+
+Supplicant::Supplicant(struct wpa_global* global) : wpa_global_(global) {}
+bool Supplicant::isValid()
+{
+	// This top level object cannot be invalidated.
+	return true;
+}
+
+Return<void> Supplicant::addInterface(
+    const IfaceInfo& iface_info, addInterface_cb _hidl_cb)
+{
+	return validateAndCall(
+	    this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
+	    &Supplicant::addInterfaceInternal, _hidl_cb, iface_info);
+}
+
+Return<void> Supplicant::removeInterface(
+    const IfaceInfo& iface_info, removeInterface_cb _hidl_cb)
+{
+	return validateAndCall(
+	    this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
+	    &Supplicant::removeInterfaceInternal, _hidl_cb, iface_info);
+}
+
+Return<void> Supplicant::getInterface(
+    const IfaceInfo& iface_info, getInterface_cb _hidl_cb)
+{
+	return validateAndCall(
+	    this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
+	    &Supplicant::getInterfaceInternal, _hidl_cb, iface_info);
+}
+
+Return<void> Supplicant::listInterfaces(listInterfaces_cb _hidl_cb)
+{
+	return validateAndCall(
+	    this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
+	    &Supplicant::listInterfacesInternal, _hidl_cb);
+}
+
+Return<void> Supplicant::registerCallback(
+    const sp<ISupplicantCallback>& callback, registerCallback_cb _hidl_cb)
+{
+	return validateAndCall(
+	    this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
+	    &Supplicant::registerCallbackInternal, _hidl_cb, callback);
+}
+
+Return<void> Supplicant::setDebugParams(
+    ISupplicant::DebugLevel level, bool show_timestamp, bool show_keys,
+    setDebugParams_cb _hidl_cb)
+{
+	return validateAndCall(
+	    this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
+	    &Supplicant::setDebugParamsInternal, _hidl_cb, level,
+	    show_timestamp, show_keys);
+}
+
+Return<void> Supplicant::setConcurrencyPriority(
+    IfaceType type, setConcurrencyPriority_cb _hidl_cb)
+{
+	return validateAndCall(
+	    this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
+	    &Supplicant::setConcurrencyPriorityInternal, _hidl_cb, type);
+}
+
+Return<ISupplicant::DebugLevel> Supplicant::getDebugLevel()
+{
+	// TODO: Add SupplicantStatus in this method return for uniformity with
+	// the other methods in supplicant HIDL interface.
+	return (ISupplicant::DebugLevel)wpa_debug_level;
+}
+
+Return<bool> Supplicant::isDebugShowTimestampEnabled()
+{
+	// TODO: Add SupplicantStatus in this method return for uniformity with
+	// the other methods in supplicant HIDL interface.
+	return ((wpa_debug_timestamp != 0) ? true : false);
+}
+
+Return<bool> Supplicant::isDebugShowKeysEnabled()
+{
+	// TODO: Add SupplicantStatus in this method return for uniformity with
+	// the other methods in supplicant HIDL interface.
+	return ((wpa_debug_show_keys != 0) ? true : false);
+}
+
+Return<void> Supplicant::terminate()
+{
+	wpa_printf(MSG_INFO, "Terminating...");
+	wpa_supplicant_terminate_proc(wpa_global_);
+	return Void();
+}
+
+std::pair<SupplicantStatus, sp<ISupplicantIface>>
+Supplicant::addInterfaceInternal(const IfaceInfo& iface_info)
+{
+	android::sp<ISupplicantIface> iface;
+
+	// Check if required |ifname| argument is empty.
+	if (iface_info.name.empty()) {
+		return {{SupplicantStatusCode::FAILURE_ARGS_INVALID, ""}, {}};
+	}
+	// Try to get the wpa_supplicant record for this iface, return
+	// the iface object with the appropriate status code if it exists.
+	SupplicantStatus status;
+	std::tie(status, iface) = getInterfaceInternal(iface_info);
+	if (status.code == SupplicantStatusCode::SUCCESS) {
+		return {{SupplicantStatusCode::FAILURE_IFACE_EXISTS, ""},
+			iface};
+	}
+
+	struct wpa_interface iface_params = {};
+	iface_params.driver = kIfaceDriverName;
+	if (iface_info.type == IfaceType::P2P) {
+		if (ensureConfigFileExists(
+			kP2pIfaceConfPath, kOldP2pIfaceConfPath) != 0) {
+			wpa_printf(
+			    MSG_ERROR, "Conf file does not exists: %s",
+			    kP2pIfaceConfPath);
+			return {{SupplicantStatusCode::FAILURE_UNKNOWN,
+				 "Conf file does not exist"},
+				{}};
+		}
+		iface_params.confname = kP2pIfaceConfPath;
+		int ret = access(kP2pIfaceConfOverlayPath, R_OK);
+		if (ret == 0) {
+			iface_params.confanother = kP2pIfaceConfOverlayPath;
+		}
+	} else {
+		if (ensureConfigFileExists(
+			kStaIfaceConfPath, kOldStaIfaceConfPath) != 0) {
+			wpa_printf(
+			    MSG_ERROR, "Conf file does not exists: %s",
+			    kStaIfaceConfPath);
+			return {{SupplicantStatusCode::FAILURE_UNKNOWN,
+				 "Conf file does not exist"},
+				{}};
+		}
+		iface_params.confname = kStaIfaceConfPath;
+		int ret = access(kStaIfaceConfOverlayPath, R_OK);
+		if (ret == 0) {
+			iface_params.confanother = kStaIfaceConfOverlayPath;
+		}
+	}
+	iface_params.ifname = iface_info.name.c_str();
+	struct wpa_supplicant* wpa_s =
+	    wpa_supplicant_add_iface(wpa_global_, &iface_params, NULL);
+	if (!wpa_s) {
+		return {{SupplicantStatusCode::FAILURE_UNKNOWN, ""}, {}};
+	}
+	// The supplicant core creates a corresponding hidl object via
+	// HidlManager when |wpa_supplicant_add_iface| is called.
+	return getInterfaceInternal(iface_info);
+}
+
+SupplicantStatus Supplicant::removeInterfaceInternal(
+    const IfaceInfo& iface_info)
+{
+	struct wpa_supplicant* wpa_s =
+	    wpa_supplicant_get_iface(wpa_global_, iface_info.name.c_str());
+	if (!wpa_s) {
+		return {SupplicantStatusCode::FAILURE_IFACE_UNKNOWN, ""};
+	}
+	if (wpa_supplicant_remove_iface(wpa_global_, wpa_s, 0)) {
+		return {SupplicantStatusCode::FAILURE_UNKNOWN, ""};
+	}
+	return {SupplicantStatusCode::SUCCESS, ""};
+}
+
+std::pair<SupplicantStatus, sp<ISupplicantIface>>
+Supplicant::getInterfaceInternal(const IfaceInfo& iface_info)
+{
+	struct wpa_supplicant* wpa_s =
+	    wpa_supplicant_get_iface(wpa_global_, iface_info.name.c_str());
+	if (!wpa_s) {
+		return {{SupplicantStatusCode::FAILURE_IFACE_UNKNOWN, ""},
+			nullptr};
+	}
+	HidlManager* hidl_manager = HidlManager::getInstance();
+	if (iface_info.type == IfaceType::P2P) {
+		android::sp<ISupplicantP2pIface> iface;
+		if (!hidl_manager ||
+		    hidl_manager->getP2pIfaceHidlObjectByIfname(
+			wpa_s->ifname, &iface)) {
+			return {{SupplicantStatusCode::FAILURE_UNKNOWN, ""},
+				iface};
+		}
+		// Set this flag true here, since there is no HIDL initialize method for the p2p
+		// config, and the supplicant interface is not ready when the p2p iface is created.
+		wpa_s->conf->persistent_reconnect = true;
+		return {{SupplicantStatusCode::SUCCESS, ""}, iface};
+	} else {
+		android::sp<ISupplicantStaIface> iface;
+		if (!hidl_manager ||
+		    hidl_manager->getStaIfaceHidlObjectByIfname(
+			wpa_s->ifname, &iface)) {
+			return {{SupplicantStatusCode::FAILURE_UNKNOWN, ""},
+				iface};
+		}
+		return {{SupplicantStatusCode::SUCCESS, ""}, iface};
+	}
+}
+
+std::pair<SupplicantStatus, std::vector<ISupplicant::IfaceInfo>>
+Supplicant::listInterfacesInternal()
+{
+	std::vector<ISupplicant::IfaceInfo> ifaces;
+	for (struct wpa_supplicant* wpa_s = wpa_global_->ifaces; wpa_s;
+	     wpa_s = wpa_s->next) {
+		if (wpa_s->global->p2p_init_wpa_s == wpa_s) {
+			ifaces.emplace_back(ISupplicant::IfaceInfo{
+			    IfaceType::P2P, wpa_s->ifname});
+		} else {
+			ifaces.emplace_back(ISupplicant::IfaceInfo{
+			    IfaceType::STA, wpa_s->ifname});
+		}
+	}
+	return {{SupplicantStatusCode::SUCCESS, ""}, std::move(ifaces)};
+}
+
+SupplicantStatus Supplicant::registerCallbackInternal(
+    const sp<ISupplicantCallback>& callback)
+{
+	HidlManager* hidl_manager = HidlManager::getInstance();
+	if (!hidl_manager ||
+	    hidl_manager->addSupplicantCallbackHidlObject(callback)) {
+		return {SupplicantStatusCode::FAILURE_UNKNOWN, ""};
+	}
+	return {SupplicantStatusCode::SUCCESS, ""};
+}
+
+SupplicantStatus Supplicant::setDebugParamsInternal(
+    ISupplicant::DebugLevel level, bool show_timestamp, bool show_keys)
+{
+	if (wpa_supplicant_set_debug_params(
+		wpa_global_, static_cast<uint32_t>(level), show_timestamp,
+		show_keys)) {
+		return {SupplicantStatusCode::FAILURE_UNKNOWN, ""};
+	}
+	return {SupplicantStatusCode::SUCCESS, ""};
+}
+
+SupplicantStatus Supplicant::setConcurrencyPriorityInternal(IfaceType type)
+{
+	if (type == IfaceType::STA) {
+		wpa_global_->conc_pref =
+		    wpa_global::wpa_conc_pref::WPA_CONC_PREF_STA;
+	} else if (type == IfaceType::P2P) {
+		wpa_global_->conc_pref =
+		    wpa_global::wpa_conc_pref::WPA_CONC_PREF_P2P;
+	} else {
+		return {SupplicantStatusCode::FAILURE_ARGS_INVALID, ""};
+	}
+	return SupplicantStatus{SupplicantStatusCode::SUCCESS, ""};
+}
+}  // namespace implementation
+}  // namespace V1_1
+}  // namespace wifi
+}  // namespace supplicant
+}  // namespace hardware
+}  // namespace android
diff --git a/wpa_supplicant/hidl/1.1/supplicant.h b/wpa_supplicant/hidl/1.1/supplicant.h
new file mode 100644
index 0000000..327e061
--- /dev/null
+++ b/wpa_supplicant/hidl/1.1/supplicant.h
@@ -0,0 +1,99 @@
+/*
+ * 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 <android/hardware/wifi/supplicant/1.1/ISupplicant.h>
+#include <android/hardware/wifi/supplicant/1.0/ISupplicantCallback.h>
+#include <android/hardware/wifi/supplicant/1.0/ISupplicantIface.h>
+
+extern "C" {
+#include "utils/common.h"
+#include "utils/includes.h"
+#include "utils/wpa_debug.h"
+#include "wpa_supplicant_i.h"
+}
+
+namespace android {
+namespace hardware {
+namespace wifi {
+namespace supplicant {
+namespace V1_1 {
+namespace implementation {
+using namespace android::hardware::wifi::supplicant::V1_0;
+
+/**
+ * Implementation of the supplicant hidl object. This hidl
+ * object is used core for global control operations on
+ * wpa_supplicant.
+ */
+class Supplicant : public V1_1::ISupplicant
+{
+public:
+	Supplicant(struct wpa_global* global);
+	~Supplicant() override = default;
+	bool isValid();
+
+	// Hidl methods exposed.
+	Return<void> addInterface(
+	    const IfaceInfo& iface_info, addInterface_cb _hidl_cb) override;
+	Return<void> removeInterface(
+	    const IfaceInfo& iface_info, removeInterface_cb _hidl_cb) override;
+	Return<void> getInterface(
+	    const IfaceInfo& iface_info, getInterface_cb _hidl_cb) override;
+	Return<void> listInterfaces(listInterfaces_cb _hidl_cb) override;
+	Return<void> registerCallback(
+	    const sp<ISupplicantCallback>& callback,
+	    registerCallback_cb _hidl_cb) override;
+	Return<void> setDebugParams(
+	    ISupplicant::DebugLevel level, bool show_timestamp, bool show_keys,
+	    setDebugParams_cb _hidl_cb) override;
+	Return<ISupplicant::DebugLevel> getDebugLevel() override;
+	Return<bool> isDebugShowTimestampEnabled() override;
+	Return<bool> isDebugShowKeysEnabled() override;
+	Return<void> setConcurrencyPriority(
+	    IfaceType type, setConcurrencyPriority_cb _hidl_cb) override;
+	Return<void> terminate() override;
+
+private:
+	// Corresponding worker functions for the HIDL methods.
+	std::pair<SupplicantStatus, sp<ISupplicantIface>> getInterfaceInternal(
+	    const IfaceInfo& iface_info);
+	std::pair<SupplicantStatus, sp<ISupplicantIface>> addInterfaceInternal(
+	    const IfaceInfo& iface_info);
+	SupplicantStatus removeInterfaceInternal(const IfaceInfo& iface_info);
+	std::pair<SupplicantStatus, std::vector<ISupplicant::IfaceInfo>>
+	listInterfacesInternal();
+	SupplicantStatus registerCallbackInternal(
+	    const sp<ISupplicantCallback>& callback);
+	SupplicantStatus setDebugParamsInternal(
+	    ISupplicant::DebugLevel level, bool show_timestamp, bool show_keys);
+	SupplicantStatus setConcurrencyPriorityInternal(IfaceType type);
+
+	// Raw pointer to the global structure maintained by the core.
+	struct wpa_global* wpa_global_;
+	// Driver name to be used for creating interfaces.
+	static const char kDriverName[];
+	// wpa_supplicant.conf file location on the device.
+	static const char kConfigFilePath[];
+
+	DISALLOW_COPY_AND_ASSIGN(Supplicant);
+};
+
+}  // namespace implementation
+}  // namespace V1_1
+}  // namespace wifi
+}  // namespace supplicant
+}  // namespace hardware
+}  // namespace android
+
+#endif  // WPA_SUPPLICANT_HIDL_SUPPLICANT_H
diff --git a/wpa_supplicant/notify.c b/wpa_supplicant/notify.c
index a5db82c..3832a33 100644
--- a/wpa_supplicant/notify.c
+++ b/wpa_supplicant/notify.c
@@ -887,6 +887,12 @@
 		     status, parameter);
 }
 
+void wpas_notify_eap_error(struct wpa_supplicant *wpa_s, int error_code)
+{
+	wpa_dbg(wpa_s, MSG_ERROR,
+		"EAP Error code = %d", error_code);
+	wpas_hidl_notify_eap_error(wpa_s, error_code);
+}
 
 void wpas_notify_network_bssid_set_changed(struct wpa_supplicant *wpa_s,
 					   struct wpa_ssid *ssid)
diff --git a/wpa_supplicant/notify.h b/wpa_supplicant/notify.h
index 26b07f5..c3ac3d1 100644
--- a/wpa_supplicant/notify.h
+++ b/wpa_supplicant/notify.h
@@ -138,6 +138,7 @@
 		      const u8 *ie, size_t ie_len, u32 ssi_signal);
 void wpas_notify_eap_status(struct wpa_supplicant *wpa_s, const char *status,
 			    const char *parameter);
+void wpas_notify_eap_error(struct wpa_supplicant *wpa_s, int error_code);
 void wpas_notify_network_bssid_set_changed(struct wpa_supplicant *wpa_s,
 					   struct wpa_ssid *ssid);
 void wpas_notify_network_type_changed(struct wpa_supplicant *wpa_s,
diff --git a/wpa_supplicant/wpa_supplicant.c b/wpa_supplicant/wpa_supplicant.c
index f8e5bf7..ee5710f 100644
--- a/wpa_supplicant/wpa_supplicant.c
+++ b/wpa_supplicant/wpa_supplicant.c
@@ -6353,7 +6353,7 @@
 			      (const u8 *) value, os_strlen(value));
 
 	rtype = wpa_supplicant_ctrl_req_from_string(field);
-	return wpa_supplicant_ctrl_rsp_handle(wpa_s, ssid, rtype, value);
+	return wpa_supplicant_ctrl_rsp_handle(wpa_s, ssid, rtype, value, strlen(value));
 #else /* IEEE8021X_EAPOL */
 	wpa_printf(MSG_DEBUG, "CTRL_IFACE: IEEE 802.1X not included");
 	return -1;
@@ -6363,16 +6363,35 @@
 int wpa_supplicant_ctrl_rsp_handle(struct wpa_supplicant *wpa_s,
 				   struct wpa_ssid *ssid,
 				   enum wpa_ctrl_req_type rtype,
-				   const char *value)
+				   const char *value, int value_len)
 {
 #ifdef IEEE8021X_EAPOL
 	struct eap_peer_config *eap = &ssid->eap;
+	char *identity, *imsi_identity;
 
 	switch (rtype) {
 	case WPA_CTRL_REQ_EAP_IDENTITY:
 		os_free(eap->identity);
-		eap->identity = (u8 *) os_strdup(value);
-		eap->identity_len = os_strlen(value);
+		os_free(eap->imsi_identity);
+		if (value == NULL)
+			return -1;
+		identity = os_strchr(value, ':');
+		if (identity == NULL) {
+			/* plain identity */
+			eap->identity = (u8 *)os_strdup(value);
+			eap->identity_len = os_strlen(value);
+		} else {
+			/* have both plain identity and encrypted identity */
+			imsi_identity = value;
+			*identity++ = '\0';
+			/* plain identity */
+			eap->imsi_identity = (u8 *)dup_binstr(imsi_identity, strlen(imsi_identity));
+			eap->imsi_identity_len = strlen(imsi_identity);
+			/* encrypted identity */
+			eap->identity = (u8 *)dup_binstr(identity,
+							 value_len - strlen(imsi_identity) - 1);
+			eap->identity_len = value_len - strlen(imsi_identity) - 1;
+		}
 		eap->pending_req_identity = 0;
 		if (ssid == wpa_s->current_ssid)
 			wpa_s->reassociate = 1;
@@ -6380,7 +6399,7 @@
 	case WPA_CTRL_REQ_EAP_PASSWORD:
 		bin_clear_free(eap->password, eap->password_len);
 		eap->password = (u8 *) os_strdup(value);
-		eap->password_len = os_strlen(value);
+		eap->password_len = value_len;
 		eap->pending_req_password = 0;
 		if (ssid == wpa_s->current_ssid)
 			wpa_s->reassociate = 1;
@@ -6388,7 +6407,7 @@
 	case WPA_CTRL_REQ_EAP_NEW_PASSWORD:
 		bin_clear_free(eap->new_password, eap->new_password_len);
 		eap->new_password = (u8 *) os_strdup(value);
-		eap->new_password_len = os_strlen(value);
+		eap->new_password_len = value_len;
 		eap->pending_req_new_password = 0;
 		if (ssid == wpa_s->current_ssid)
 			wpa_s->reassociate = 1;
@@ -6403,7 +6422,7 @@
 	case WPA_CTRL_REQ_EAP_OTP:
 		bin_clear_free(eap->otp, eap->otp_len);
 		eap->otp = (u8 *) os_strdup(value);
-		eap->otp_len = os_strlen(value);
+		eap->otp_len = value_len;
 		os_free(eap->pending_req_otp);
 		eap->pending_req_otp = NULL;
 		eap->pending_req_otp_len = 0;
diff --git a/wpa_supplicant/wpa_supplicant_i.h b/wpa_supplicant/wpa_supplicant_i.h
index d0172fa..acde7c5 100644
--- a/wpa_supplicant/wpa_supplicant_i.h
+++ b/wpa_supplicant/wpa_supplicant_i.h
@@ -1389,7 +1389,7 @@
 int wpa_supplicant_ctrl_rsp_handle(struct wpa_supplicant *wpa_s,
 				   struct wpa_ssid *ssid,
 				   enum wpa_ctrl_req_type rtype,
-				   const char *value);
+				   const char *value, int len);
 
 void ibss_mesh_setup_freq(struct wpa_supplicant *wpa_s,
 			  const struct wpa_ssid *ssid,
diff --git a/wpa_supplicant/wpas_glue.c b/wpa_supplicant/wpas_glue.c
index e44f6af..e29f13b 100644
--- a/wpa_supplicant/wpas_glue.c
+++ b/wpa_supplicant/wpas_glue.c
@@ -1037,6 +1037,12 @@
 	wpas_notify_eap_status(wpa_s, status, parameter);
 }
 
+static void wpa_supplicant_eap_error_cb(void *ctx, int error_code)
+{
+	struct wpa_supplicant *wpa_s = ctx;
+
+	wpas_notify_eap_error(wpa_s, error_code);
+}
 
 static void wpa_supplicant_set_anon_id(void *ctx, const u8 *id, size_t len)
 {
@@ -1115,6 +1121,7 @@
 	ctx->cert_cb = wpa_supplicant_cert_cb;
 	ctx->cert_in_cb = wpa_s->conf->cert_in_cb;
 	ctx->status_cb = wpa_supplicant_status_cb;
+	ctx->eap_error_cb = wpa_supplicant_eap_error_cb;
 	ctx->set_anon_id = wpa_supplicant_set_anon_id;
 	ctx->cb_ctx = wpa_s;
 	wpa_s->eapol = eapol_sm_init(ctx);