Merge "Cumulative patch from commit 05e5e615e6a26d7a9f5bd0569a0baeae1bcdee49"
diff --git a/hostapd/hostapd.android.rc b/hostapd/hostapd.android.rc
index eee4b53..0ae27ca 100644
--- a/hostapd/hostapd.android.rc
+++ b/hostapd/hostapd.android.rc
@@ -14,7 +14,7 @@
         /data/misc/wifi/hostapd.conf
     class main
     user wifi
-    group wifi net_raw
+    group wifi
     writepid /data/misc/wifi/hostapd.pid
     disabled
     oneshot
diff --git a/wpa_supplicant/Android.mk b/wpa_supplicant/Android.mk
index 499eb73..afbe336 100644
--- a/wpa_supplicant/Android.mk
+++ b/wpa_supplicant/Android.mk
@@ -1673,6 +1673,7 @@
 LOCAL_SRC_FILES := \
     hidl/hidl.cpp \
     hidl/hidl_manager.cpp \
+    hidl/iface_config_utils.cpp \
     hidl/p2p_iface.cpp \
     hidl/p2p_network.cpp \
     hidl/sta_iface.cpp \
diff --git a/wpa_supplicant/hidl/hidl.cpp b/wpa_supplicant/hidl/hidl.cpp
index d8988b9..e38288b 100644
--- a/wpa_supplicant/hidl/hidl.cpp
+++ b/wpa_supplicant/hidl/hidl.cpp
@@ -25,10 +25,8 @@
 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 */)
 {
-	struct wpas_hidl_priv *priv = (wpas_hidl_priv *)sock_ctx;
-	wpa_printf(MSG_DEBUG, "Processing hidl events on FD %d", priv->hidl_fd);
 	IPCThreadState::self()->handlePolledCommands();
 }
 
@@ -290,3 +288,51 @@
 
 	hidl_manager->notifyAssocReject(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);
+}
diff --git a/wpa_supplicant/hidl/hidl.h b/wpa_supplicant/hidl/hidl.h
index 0e51b3c..e191c26 100644
--- a/wpa_supplicant/hidl/hidl.h
+++ b/wpa_supplicant/hidl/hidl.h
@@ -48,6 +48,11 @@
     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_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);
 #else   // CONFIG_CTRL_IFACE_HIDL
 static inline int wpas_hidl_register_interface(struct wpa_supplicant *wpa_s)
 {
@@ -97,6 +102,15 @@
 }
 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_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_wps_event_success(struct wpa_supplicant *wpa_s) {}
+static void wpas_hidl_notify_wps_event_pbc_overlap(struct wpa_supplicant *wpa_s)
+{
+}
 #endif  // CONFIG_CTRL_IFACE_HIDL
 
 #ifdef _cplusplus
diff --git a/wpa_supplicant/hidl/hidl_manager.cpp b/wpa_supplicant/hidl/hidl_manager.cpp
index ec6b847..2490151 100644
--- a/wpa_supplicant/hidl/hidl_manager.cpp
+++ b/wpa_supplicant/hidl/hidl_manager.cpp
@@ -306,7 +306,6 @@
 namespace V1_0 {
 namespace implementation {
 
-const char HidlManager::kServiceName[] = "wpa_supplicant";
 HidlManager *HidlManager::instance_ = NULL;
 
 HidlManager *HidlManager::getInstance()
@@ -327,8 +326,7 @@
 {
 	// Create the main hidl service object and register it.
 	supplicant_object_ = new Supplicant(global);
-	if (supplicant_object_->registerAsService(kServiceName) !=
-	    android::NO_ERROR) {
+	if (supplicant_object_->registerAsService() != android::NO_ERROR) {
 		return 1;
 	}
 	return 0;
@@ -531,7 +529,7 @@
 	// Invoke the |onStateChanged| method on all registered callbacks.
 	ISupplicantStaIfaceCallback::State hidl_state =
 	    static_cast<ISupplicantStaIfaceCallback::State>(wpa_s->wpa_state);
-	std::array<uint8_t, 6> hidl_bssid;
+	std::array<uint8_t, ETH_ALEN> hidl_bssid;
 	os_memcpy(hidl_bssid.data(), wpa_s->bssid, ETH_ALEN);
 	uint32_t hidl_network_id = UINT32_MAX;
 	std::vector<uint8_t> hidl_ssid;
@@ -621,7 +619,7 @@
 		    convertWpaBufToVector(anqp->hs20_osu_providers_list);
 	}
 
-	std::array<uint8_t, 6> hidl_bssid;
+	std::array<uint8_t, ETH_ALEN> hidl_bssid;
 	os_memcpy(hidl_bssid.data(), bssid, ETH_ALEN);
 	callWithEachStaIfaceCallback(
 	    wpa_s->ifname, std::bind(
@@ -651,7 +649,7 @@
 		return;
 
 	std::vector<uint8_t> hidl_image(image, image + image_length);
-	std::array<uint8_t, 6> hidl_bssid;
+	std::array<uint8_t, ETH_ALEN> hidl_bssid;
 	os_memcpy(hidl_bssid.data(), bssid, ETH_ALEN);
 	callWithEachStaIfaceCallback(
 	    wpa_s->ifname,
@@ -739,7 +737,7 @@
 	if (is_zero_ether_addr(bssid)) {
 		bssid = wpa_s->pending_bssid;
 	}
-	std::array<uint8_t, 6> hidl_bssid;
+	std::array<uint8_t, ETH_ALEN> hidl_bssid;
 	os_memcpy(hidl_bssid.data(), bssid, ETH_ALEN);
 
 	callWithEachStaIfaceCallback(
@@ -770,7 +768,7 @@
 	if (is_zero_ether_addr(bssid)) {
 		bssid = wpa_s->pending_bssid;
 	}
-	std::array<uint8_t, 6> hidl_bssid;
+	std::array<uint8_t, ETH_ALEN> hidl_bssid;
 	os_memcpy(hidl_bssid.data(), bssid, ETH_ALEN);
 
 	callWithEachStaIfaceCallback(
@@ -780,6 +778,99 @@
 		std::placeholders::_1, hidl_bssid, wpa_s->assoc_status_code));
 }
 
+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;
+
+	const std::string ifname(wpa_s->ifname);
+	if (sta_iface_object_map_.find(ifname) == sta_iface_object_map_.end())
+		return;
+
+	std::array<uint8_t, ETH_ALEN> hidl_bssid;
+	os_memcpy(hidl_bssid.data(), peer_macaddr, ETH_ALEN);
+
+	ISupplicantStaIfaceCallback::WpsConfigError hidl_config_error =
+	    static_cast<ISupplicantStaIfaceCallback::WpsConfigError>(
+		config_error);
+	ISupplicantStaIfaceCallback::WpsErrorIndication hidl_error_indication =
+	    static_cast<ISupplicantStaIfaceCallback::WpsErrorIndication>(
+		error_indication);
+
+	callWithEachStaIfaceCallback(
+	    wpa_s->ifname, std::bind(
+			       &ISupplicantStaIfaceCallback::onWpsEventFail,
+			       std::placeholders::_1, hidl_bssid,
+			       hidl_config_error, hidl_error_indication));
+}
+
+void HidlManager::notifyWpsEventSuccess(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;
+
+	callWithEachStaIfaceCallback(
+	    wpa_s->ifname, std::bind(
+			       &ISupplicantStaIfaceCallback::onWpsEventSuccess,
+			       std::placeholders::_1));
+}
+
+void HidlManager::notifyWpsEventPbcOverlap(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;
+
+	callWithEachStaIfaceCallback(
+	    wpa_s->ifname,
+	    std::bind(
+		&ISupplicantStaIfaceCallback::onWpsEventPbcOverlap,
+		std::placeholders::_1));
+}
+
+void HidlManager::notifyExtRadioWorkStart(
+    struct wpa_supplicant *wpa_s, uint32_t id)
+{
+	if (!wpa_s)
+		return;
+
+	const std::string ifname(wpa_s->ifname);
+	if (sta_iface_object_map_.find(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;
+
+	const std::string ifname(wpa_s->ifname);
+	if (sta_iface_object_map_.find(ifname) == sta_iface_object_map_.end())
+		return;
+
+	callWithEachStaIfaceCallback(
+	    wpa_s->ifname,
+	    std::bind(
+		&ISupplicantStaIfaceCallback::onExtRadioWorkTimeout,
+		std::placeholders::_1, id));
+}
+
 /**
  * Retrieve the |ISupplicantP2pIface| hidl object reference using the provided
  * ifname.
diff --git a/wpa_supplicant/hidl/hidl_manager.h b/wpa_supplicant/hidl/hidl_manager.h
index 8c4aa7f..14fd726 100644
--- a/wpa_supplicant/hidl/hidl_manager.h
+++ b/wpa_supplicant/hidl/hidl_manager.h
@@ -76,8 +76,17 @@
 	    const char *url);
 	void notifyDisconnectReason(struct wpa_supplicant *wpa_s);
 	void notifyAssocReject(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);
 
 	// 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);
@@ -146,8 +155,6 @@
 	    const std::function<android::hardware::Return<void>(
 		android::sp<ISupplicantStaNetworkCallback>)> &method);
 
-	// HIDL Service name.
-	static const char kServiceName[];
 	// Singleton instance of this class.
 	static HidlManager *instance_;
 	// The main hidl service object.
@@ -266,6 +273,18 @@
 	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");
@@ -306,6 +325,11 @@
 	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");
@@ -375,40 +399,236 @@
     "HS Subtype value mismatch");
 
 static_assert(
-    static_cast<uint32_t>(
-	ISupplicantP2pIface::GroupCapabilityMask::GROUP_OWNER) ==
+    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>(
-	ISupplicantP2pIface::GroupCapabilityMask::PERSISTENT_GROUP) ==
+    static_cast<uint32_t>(P2pGroupCapabilityMask::PERSISTENT_GROUP) ==
 	P2P_GROUP_CAPAB_PERSISTENT_GROUP,
     "P2P capability value mismatch");
 static_assert(
-    static_cast<uint32_t>(
-	ISupplicantP2pIface::GroupCapabilityMask::GROUP_LIMIT) ==
+    static_cast<uint32_t>(P2pGroupCapabilityMask::GROUP_LIMIT) ==
 	P2P_GROUP_CAPAB_GROUP_LIMIT,
     "P2P capability value mismatch");
 static_assert(
-    static_cast<uint32_t>(
-	ISupplicantP2pIface::GroupCapabilityMask::INTRA_BSS_DIST) ==
+    static_cast<uint32_t>(P2pGroupCapabilityMask::INTRA_BSS_DIST) ==
 	P2P_GROUP_CAPAB_INTRA_BSS_DIST,
     "P2P capability value mismatch");
 static_assert(
-    static_cast<uint32_t>(
-	ISupplicantP2pIface::GroupCapabilityMask::CROSS_CONN) ==
+    static_cast<uint32_t>(P2pGroupCapabilityMask::CROSS_CONN) ==
 	P2P_GROUP_CAPAB_CROSS_CONN,
     "P2P capability value mismatch");
 static_assert(
-    static_cast<uint32_t>(
-	ISupplicantP2pIface::GroupCapabilityMask::PERSISTENT_RECONN) ==
+    static_cast<uint32_t>(P2pGroupCapabilityMask::PERSISTENT_RECONN) ==
 	P2P_GROUP_CAPAB_PERSISTENT_RECONN,
     "P2P capability value mismatch");
 static_assert(
-    static_cast<uint32_t>(
-	ISupplicantP2pIface::GroupCapabilityMask::GROUP_FORMATION) ==
+    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_0
 }  // namespace wifi
diff --git a/wpa_supplicant/hidl/iface_config_utils.cpp b/wpa_supplicant/hidl/iface_config_utils.cpp
new file mode 100644
index 0000000..028eae8
--- /dev/null
+++ b/wpa_supplicant/hidl/iface_config_utils.cpp
@@ -0,0 +1,177 @@
+/*
+ * 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 = 64;
+constexpr uint32_t kMaxWpsModelNameSize = 32;
+constexpr uint32_t kMaxWpsModelNumberSize = 32;
+constexpr uint32_t kMaxWpsSerialNumberSize = 32;
+
+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, "pushbutton"},
+	      {WpsConfigMethods::KEYPAD, "keypad"},
+	      {WpsConfigMethods::VIRT_PUSHBUTTON, "virt_pushbutton"},
+	      {WpsConfigMethods::PHY_PUSHBUTTON, "phy_pushbutton"},
+	      {WpsConfigMethods::P2PS, "p2ps"},
+	      {WpsConfigMethods::VIRT_DISPLAY, "virt_display"},
+	      {WpsConfigMethods::PHY_DISPLAY, "phy_display"}}) {
+		if (config_methods & flag_and_name.first) {
+			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_0 {
+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_0
+}  // namespace wifi
+}  // namespace supplicant
+}  // namespace hardware
+}  // namespace android
diff --git a/wpa_supplicant/hidl/iface_config_utils.h b/wpa_supplicant/hidl/iface_config_utils.h
new file mode 100644
index 0000000..789cc38
--- /dev/null
+++ b/wpa_supplicant/hidl/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_0 {
+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_0
+}  // namespace wifi
+}  // namespace supplicant
+}  // namespace hardware
+}  // namespace android
+
+#endif  // WPA_SUPPLICANT_HIDL_IFACE_CONFIG_UTILS_H
diff --git a/wpa_supplicant/hidl/p2p_iface.cpp b/wpa_supplicant/hidl/p2p_iface.cpp
index 857fe1a..706ac1a 100644
--- a/wpa_supplicant/hidl/p2p_iface.cpp
+++ b/wpa_supplicant/hidl/p2p_iface.cpp
@@ -9,13 +9,20 @@
 
 #include "hidl_manager.h"
 #include "hidl_return_util.h"
+#include "iface_config_utils.h"
 #include "p2p_iface.h"
 
+extern "C" {
+#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;
 
 using android::hardware::wifi::supplicant::V1_0::ISupplicantP2pIface;
 uint8_t convertHidlMiracastModeToInternal(
@@ -348,6 +355,113 @@
 	    &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, 8>& info, setWfdDeviceInfo_cb _hidl_cb)
+{
+	return validateAndCall(
+	    this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
+	    &P2pIface::setWfdDeviceInfoInternal, _hidl_cb, info);
+}
+
 std::pair<SupplicantStatus, std::string> P2pIface::getNameInternal()
 {
 	return {{SupplicantStatusCode::SUCCESS, ""}, ifname_};
@@ -876,6 +990,146 @@
 	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();
+	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, ""};
+	}
+	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, ""}, ""};
+	}
+	std::string pin_str;
+	pin_str.reserve(9);
+	snprintf(&pin_str[0], pin_str.size(), "%08d", pin);
+	return {{SupplicantStatusCode::SUCCESS, ""}, pin_str};
+}
+
+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 hidl_array<uint8_t, 8>& info)
+{
+	struct wpa_supplicant* wpa_s = retrieveIfacePtr();
+	uint32_t wfd_device_info_hex_len = info.size() * 2 + 1;
+	std::vector<char> wfd_device_info_hex(wfd_device_info_hex_len);
+	wpa_snprintf_hex(
+	    wfd_device_info_hex.data(), wfd_device_info_hex.size(), info.data(),
+	    info.size());
+	std::string wfd_device_info_set_cmd_str =
+	    std::to_string(kWfdDeviceInfoSubelemId) + " " +
+	    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, ""};
+}
+
 /**
  * Retrieve the underlying |wpa_supplicant| struct
  * pointer for this iface.
diff --git a/wpa_supplicant/hidl/p2p_iface.h b/wpa_supplicant/hidl/p2p_iface.h
index 5c814ae..07551bd 100644
--- a/wpa_supplicant/hidl/p2p_iface.h
+++ b/wpa_supplicant/hidl/p2p_iface.h
@@ -140,6 +140,40 @@
 	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, 8>& info,
+	    setWfdDeviceInfo_cb _hidl_cb) override;
 
 private:
 	// Corresponding worker functions for the HIDL methods.
@@ -212,6 +246,29 @@
 	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 hidl_array<uint8_t, 8>& info);
 
 	struct wpa_supplicant* retrieveIfacePtr();
 	struct wpa_supplicant* retrieveGroupIfacePtr(
diff --git a/wpa_supplicant/hidl/p2p_network.cpp b/wpa_supplicant/hidl/p2p_network.cpp
index ce02179..788f99c 100644
--- a/wpa_supplicant/hidl/p2p_network.cpp
+++ b/wpa_supplicant/hidl/p2p_network.cpp
@@ -11,6 +11,10 @@
 #include "hidl_return_util.h"
 #include "p2p_network.h"
 
+extern "C" {
+#include "config_ssid.h"
+}
+
 namespace android {
 namespace hardware {
 namespace wifi {
@@ -64,6 +68,41 @@
 	    &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);
+}
+
 std::pair<SupplicantStatus, uint32_t> P2pNetwork::getIdInternal()
 {
 	return {{SupplicantStatusCode::SUCCESS, ""}, network_id_};
@@ -91,6 +130,45 @@
 	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)};
+}
+
 /**
  * Retrieve the underlying |wpa_ssid| struct pointer for
  * this network.
diff --git a/wpa_supplicant/hidl/p2p_network.h b/wpa_supplicant/hidl/p2p_network.h
index 023e902..d09a6be 100644
--- a/wpa_supplicant/hidl/p2p_network.h
+++ b/wpa_supplicant/hidl/p2p_network.h
@@ -18,12 +18,7 @@
 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 {
@@ -55,6 +50,11 @@
 	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;
 
 private:
 	// Corresponding worker functions for the HIDL methods.
@@ -63,6 +63,11 @@
 	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();
 
 	struct wpa_ssid* retrieveNetworkPtr();
 	struct wpa_supplicant* retrieveIfacePtr();
diff --git a/wpa_supplicant/hidl/sta_iface.cpp b/wpa_supplicant/hidl/sta_iface.cpp
index a513260..8ce80bb 100644
--- a/wpa_supplicant/hidl/sta_iface.cpp
+++ b/wpa_supplicant/hidl/sta_iface.cpp
@@ -9,15 +9,23 @@
 
 #include "hidl_manager.h"
 #include "hidl_return_util.h"
+#include "iface_config_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_0::ISupplicantStaIface;
+using android::hardware::wifi::supplicant::V1_0::SupplicantStatus;
+using android::hardware::wifi::supplicant::V1_0::SupplicantStatusCode;
+using android::hardware::wifi::supplicant::V1_0::implementation::HidlManager;
+
 constexpr uint32_t kMaxAnqpElems = 100;
 constexpr char kGetMacAddress[] = "MACADDR";
 constexpr char kStartRxFilter[] = "RXFILTER-START";
@@ -30,10 +38,9 @@
 constexpr char kSetSupendModeEnabled[] = "SETSUSPENDMODE 1";
 constexpr char kSetSupendModeDisabled[] = "SETSUSPENDMODE 0";
 constexpr char kSetCountryCode[] = "COUNTRY ";
-
-using android::hardware::wifi::supplicant::V1_0::ISupplicantStaIface;
-using android::hardware::wifi::supplicant::V1_0::SupplicantStatus;
-using android::hardware::wifi::supplicant::V1_0::SupplicantStatusCode;
+constexpr uint32_t kExtRadioWorkDefaultTimeoutInSec = static_cast<uint32_t>(
+    ISupplicantStaIface::ExtRadioWorkDefaults::TIMEOUT_IN_SECS);
+constexpr char kExtRadioWorkNamePrefix[] = "ext:";
 
 uint8_t convertHidlRxFilterTypeToInternal(
     ISupplicantStaIface::RxFilterType type)
@@ -87,6 +94,60 @@
 	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 {
@@ -305,6 +366,128 @@
 	    &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);
+}
+
 std::pair<SupplicantStatus, std::string> StaIface::getNameInternal()
 {
 	return {{SupplicantStatusCode::SUCCESS, ""}, ifname_};
@@ -498,11 +681,7 @@
 	if (info_elements.size() > kMaxAnqpElems) {
 		return {SupplicantStatusCode::FAILURE_ARGS_INVALID, ""};
 	}
-	uint16_t *info_elems_buf = static_cast<uint16_t *>(
-	    os_malloc(sizeof(uint16_t) * info_elements.size()));
-	if (!info_elems_buf) {
-		return {SupplicantStatusCode::FAILURE_UNKNOWN, ""};
-	}
+	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++] =
@@ -643,6 +822,172 @@
 	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, ""}, ""};
+	}
+	std::string pin_str;
+	pin_str.reserve(9);
+	snprintf(&pin_str[0], pin_str.size(), "%08d", pin);
+	return {{SupplicantStatusCode::SUCCESS, ""}, pin_str};
+}
+
+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, ""};
+}
+
 /**
  * Retrieve the underlying |wpa_supplicant| struct
  * pointer for this iface.
diff --git a/wpa_supplicant/hidl/sta_iface.h b/wpa_supplicant/hidl/sta_iface.h
index 3910143..32e0e7c 100644
--- a/wpa_supplicant/hidl/sta_iface.h
+++ b/wpa_supplicant/hidl/sta_iface.h
@@ -115,6 +115,44 @@
 	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;
 
 private:
 	// Corresponding worker functions for the HIDL methods.
@@ -161,6 +199,30 @@
 	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);
 
 	struct wpa_supplicant* retrieveIfacePtr();
 
diff --git a/wpa_supplicant/hidl/sta_network.cpp b/wpa_supplicant/hidl/sta_network.cpp
index 226c1bd..cae61e6 100644
--- a/wpa_supplicant/hidl/sta_network.cpp
+++ b/wpa_supplicant/hidl/sta_network.cpp
@@ -21,7 +21,10 @@
     (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::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 kAllowedproto_mask =
     (static_cast<uint32_t>(ISupplicantStaNetwork::ProtoMask::WPA) |
      static_cast<uint32_t>(ISupplicantStaNetwork::ProtoMask::RSN) |
@@ -34,7 +37,9 @@
     (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::CCMP) |
+     static_cast<uint32_t>(
+	 ISupplicantStaNetwork::GroupCipherMask::GTK_NOT_USED));
 constexpr uint32_t kAllowedpairwise_cipher_mask =
     (static_cast<uint32_t>(ISupplicantStaNetwork::PairwiseCipherMask::NONE) |
      static_cast<uint32_t>(ISupplicantStaNetwork::PairwiseCipherMask::TKIP) |
@@ -50,6 +55,11 @@
     "NULL", "PAP", "MSCHAP", "MSCHAPV2", "GTC"};
 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 {
@@ -312,6 +322,30 @@
 	    &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(
@@ -497,6 +531,13 @@
 	    &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::enable(bool no_connect, enable_cb _hidl_cb)
 {
 	return validateAndCall(
@@ -519,13 +560,22 @@
 }
 
 Return<void> StaNetwork::sendNetworkEapSimGsmAuthResponse(
-    const ISupplicantStaNetwork::NetworkResponseEapSimGsmAuthParams &params,
+    const hidl_vec<ISupplicantStaNetwork::NetworkResponseEapSimGsmAuthParams>
+	&vec_params,
     sendNetworkEapSimGsmAuthResponse_cb _hidl_cb)
 {
 	return validateAndCall(
 	    this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
 	    &StaNetwork::sendNetworkEapSimGsmAuthResponseInternal, _hidl_cb,
-	    params);
+	    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(
@@ -538,6 +588,24 @@
 	    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)
@@ -986,6 +1054,34 @@
 	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();
@@ -1274,6 +1370,15 @@
 		{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}};
+}
+
 SupplicantStatus StaNetwork::enableInternal(bool no_connect)
 {
 	struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
@@ -1316,27 +1421,27 @@
 }
 
 SupplicantStatus StaNetwork::sendNetworkEapSimGsmAuthResponseInternal(
-    const ISupplicantStaNetwork::NetworkResponseEapSimGsmAuthParams &params)
+    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;
-	uint32_t kc_hex_len = params.kc.size() * 2 + 1;
-	char *kc_hex = (char *)malloc(kc_hex_len);
-	uint32_t sres_hex_len = params.sres.size() * 2 + 1;
-	char *sres_hex = (char *)malloc(sres_hex_len);
-	if (!kc_hex || !sres_hex) {
-		return {SupplicantStatusCode::FAILURE_UNKNOWN, ""};
+	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());
 	}
-	wpa_snprintf_hex(
-	    kc_hex, kc_hex_len, params.kc.data(), params.kc.size());
-	wpa_snprintf_hex(
-	    sres_hex, sres_hex_len, params.sres.data(), params.sres.size());
-	ctrl_rsp_param += "kc:";
-	ctrl_rsp_param += kc_hex;
-	ctrl_rsp_param += " sres:";
-	ctrl_rsp_param += sres_hex;
 	enum wpa_ctrl_req_type rtype = WPA_CTRL_REQ_SIM;
 	struct wpa_supplicant *wpa_s = retrieveIfacePtr();
 	if (wpa_supplicant_ctrl_rsp_handle(
@@ -1350,34 +1455,42 @@
 	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)) {
+		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.
-	std::string ctrl_rsp_param;
 	uint32_t ik_hex_len = params.ik.size() * 2 + 1;
-	char *ik_hex = (char *)malloc(ik_hex_len);
+	std::vector<char> ik_hex(ik_hex_len);
 	uint32_t ck_hex_len = params.ck.size() * 2 + 1;
-	char *ck_hex = (char *)malloc(ck_hex_len);
+	std::vector<char> ck_hex(ck_hex_len);
 	uint32_t res_hex_len = params.res.size() * 2 + 1;
-	char *res_hex = (char *)malloc(res_hex_len);
-	if (!ik_hex || !ck_hex || !res_hex) {
-		return {SupplicantStatusCode::FAILURE_UNKNOWN, ""};
-	}
+	std::vector<char> res_hex(res_hex_len);
 	wpa_snprintf_hex(
-	    ik_hex, ik_hex_len, params.ik.data(), params.ik.size());
+	    ik_hex.data(), ik_hex.size(), params.ik.data(), params.ik.size());
 	wpa_snprintf_hex(
-	    ck_hex, ck_hex_len, params.ck.data(), params.ck.size());
+	    ck_hex.data(), ck_hex.size(), params.ck.data(), params.ck.size());
 	wpa_snprintf_hex(
-	    res_hex, res_hex_len, params.res.data(), params.res.size());
-	ctrl_rsp_param += "ik:";
-	ctrl_rsp_param += ik_hex;
-	ctrl_rsp_param += "ck:";
-	ctrl_rsp_param += ck_hex;
-	ctrl_rsp_param += " res:";
-	ctrl_rsp_param += res_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(
@@ -1391,6 +1504,43 @@
 	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())) {
+		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)) {
+		return {SupplicantStatusCode::FAILURE_UNKNOWN, ""};
+	}
+	eapol_sm_notify_ctrl_response(wpa_s->eapol);
+	return {SupplicantStatusCode::SUCCESS, ""};
+}
+
 SupplicantStatus StaNetwork::sendNetworkEapIdentityResponseInternal(
     const std::vector<uint8_t> &identity)
 {
@@ -1398,14 +1548,11 @@
 	// Convert the incoming parameters to a string to pass to
 	// wpa_supplicant.
 	uint32_t identity_hex_len = identity.size() * 2 + 1;
-	char *identity_hex = (char *)malloc(identity_hex_len);
-	std::string ctrl_rsp_param;
-	if (!identity_hex) {
-		return {SupplicantStatusCode::FAILURE_UNKNOWN, ""};
-	}
+	std::vector<char> identity_hex(identity_hex_len);
 	wpa_snprintf_hex(
-	    identity_hex, identity_hex_len, identity.data(), identity.size());
-	ctrl_rsp_param = identity_hex;
+	    identity_hex.data(), identity_hex.size(), identity.data(),
+	    identity.size());
+	std::string ctrl_rsp_param = identity_hex.data();
 	enum wpa_ctrl_req_type rtype = WPA_CTRL_REQ_EAP_IDENTITY;
 	struct wpa_supplicant *wpa_s = retrieveIfacePtr();
 	if (wpa_supplicant_ctrl_rsp_handle(
diff --git a/wpa_supplicant/hidl/sta_network.h b/wpa_supplicant/hidl/sta_network.h
index 68ab139..063fa61 100644
--- a/wpa_supplicant/hidl/sta_network.h
+++ b/wpa_supplicant/hidl/sta_network.h
@@ -118,6 +118,12 @@
 	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;
@@ -150,17 +156,26 @@
 	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> 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 ISupplicantStaNetwork::NetworkResponseEapSimGsmAuthParams&
-		params,
+	    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;
@@ -207,6 +222,9 @@
 	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();
@@ -241,15 +259,21 @@
 	std::pair<SupplicantStatus, std::string> getEapEngineIDInternal();
 	std::pair<SupplicantStatus, std::string>
 	getEapDomainSuffixMatchInternal();
+	std::pair<SupplicantStatus, std::string> getIdStrInternal();
 	SupplicantStatus enableInternal(bool no_connect);
 	SupplicantStatus disableInternal();
 	SupplicantStatus selectInternal();
 	SupplicantStatus sendNetworkEapSimGsmAuthResponseInternal(
-	    const ISupplicantStaNetwork::NetworkResponseEapSimGsmAuthParams&
-		params);
+	    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);
 
diff --git a/wpa_supplicant/notify.c b/wpa_supplicant/notify.c
index 5dac806..3fdb36f 100644
--- a/wpa_supplicant/notify.c
+++ b/wpa_supplicant/notify.c
@@ -299,6 +299,10 @@
 
 #ifdef CONFIG_WPS
 	wpas_dbus_signal_wps_event_fail(wpa_s, fail);
+
+	wpas_hidl_notify_wps_event_fail(wpa_s, fail->peer_macaddr,
+					fail->config_error,
+					fail->error_indication);
 #endif /* CONFIG_WPS */
 }
 
@@ -310,6 +314,8 @@
 
 #ifdef CONFIG_WPS
 	wpas_dbus_signal_wps_event_success(wpa_s);
+
+	wpas_hidl_notify_wps_event_success(wpa_s);
 #endif /* CONFIG_WPS */
 }
 
@@ -320,6 +326,8 @@
 
 #ifdef CONFIG_WPS
 	wpas_dbus_signal_wps_event_pbc_overlap(wpa_s);
+
+	wpas_hidl_notify_wps_event_pbc_overlap(wpa_s);
 #endif /* CONFIG_WPS */
 }