Merge changes from topics 'hidl-register-fail-gracefully', 'anqp_hidl', 'supplicant_p2p'

* changes:
  wpa_supplicant(hidl): Add network param getters
  wpa_supplicant(hidl): Turn on HIDL control interface
  wpa_supplicant(hidl): Invoke disconnect/assoc reject calbacks
  wpa_supplicant(hidl): Invoke ANQP callbacks
  wpa_supplicant: Add notifications for ANQP/HS20 events
  wpa_supplicant(hidl): Implement ANQP query requests
  wpa_supplicant(hidl): P2P Iface implementation
diff --git a/wpa_supplicant/android.config b/wpa_supplicant/android.config
index 84044fc..2a5c810 100644
--- a/wpa_supplicant/android.config
+++ b/wpa_supplicant/android.config
@@ -326,7 +326,7 @@
 
 # Add support for Hidl control interface
 # Only applicable for Android platforms.
-# CONFIG_CTRL_IFACE_HIDL=y
+CONFIG_CTRL_IFACE_HIDL=y
 
 # Add support for loading EAP methods dynamically as shared libraries.
 # When this option is enabled, each EAP method can be either included
diff --git a/wpa_supplicant/hidl/hidl.cpp b/wpa_supplicant/hidl/hidl.cpp
index 599938d..09f09ce 100644
--- a/wpa_supplicant/hidl/hidl.cpp
+++ b/wpa_supplicant/hidl/hidl.cpp
@@ -181,3 +181,112 @@
 	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);
+}
diff --git a/wpa_supplicant/hidl/hidl.h b/wpa_supplicant/hidl/hidl.h
index ee7cab1..0e51b3c 100644
--- a/wpa_supplicant/hidl/hidl.h
+++ b/wpa_supplicant/hidl/hidl.h
@@ -36,6 +36,18 @@
 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);
 #else   // CONFIG_CTRL_IFACE_HIDL
 static inline int wpas_hidl_register_interface(struct wpa_supplicant *wpa_s)
 {
@@ -65,6 +77,26 @@
 {
 	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) {}
 #endif  // CONFIG_CTRL_IFACE_HIDL
 
 #ifdef _cplusplus
diff --git a/wpa_supplicant/hidl/hidl_manager.cpp b/wpa_supplicant/hidl/hidl_manager.cpp
index 90a0c22..ec6b847 100644
--- a/wpa_supplicant/hidl/hidl_manager.cpp
+++ b/wpa_supplicant/hidl/hidl_manager.cpp
@@ -287,6 +287,16 @@
 		method(callback);
 	}
 }
+
+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>();
+	}
+}
 }  // namespace
 
 namespace android {
@@ -521,7 +531,7 @@
 	// Invoke the |onStateChanged| method on all registered callbacks.
 	ISupplicantStaIfaceCallback::State hidl_state =
 	    static_cast<ISupplicantStaIfaceCallback::State>(wpa_s->wpa_state);
-	hidl_array<uint8_t, 6> hidl_bssid;
+	std::array<uint8_t, 6> 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;
@@ -567,6 +577,210 @@
 }
 
 /**
+ * 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;
+
+	const std::string ifname(wpa_s->ifname);
+	if (sta_iface_object_map_.find(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 =
+		    convertWpaBufToVector(anqp->venue_name);
+		hidl_anqp_data.roamingConsortium =
+		    convertWpaBufToVector(anqp->roaming_consortium);
+		hidl_anqp_data.ipAddrTypeAvailability =
+		    convertWpaBufToVector(anqp->ip_addr_type_availability);
+		hidl_anqp_data.naiRealm =
+		    convertWpaBufToVector(anqp->nai_realm);
+		hidl_anqp_data.anqp3gppCellularNetwork =
+		    convertWpaBufToVector(anqp->anqp_3gpp);
+		hidl_anqp_data.domainName =
+		    convertWpaBufToVector(anqp->domain_name);
+
+		hidl_hs20_anqp_data.operatorFriendlyName =
+		    convertWpaBufToVector(anqp->hs20_operator_friendly_name);
+		hidl_hs20_anqp_data.wanMetrics =
+		    convertWpaBufToVector(anqp->hs20_wan_metrics);
+		hidl_hs20_anqp_data.connectionCapability =
+		    convertWpaBufToVector(anqp->hs20_connection_capability);
+		hidl_hs20_anqp_data.osuProvidersList =
+		    convertWpaBufToVector(anqp->hs20_osu_providers_list);
+	}
+
+	std::array<uint8_t, 6> hidl_bssid;
+	os_memcpy(hidl_bssid.data(), bssid, ETH_ALEN);
+	callWithEachStaIfaceCallback(
+	    wpa_s->ifname, std::bind(
+			       &ISupplicantStaIfaceCallback::onAnqpQueryDone,
+			       std::placeholders::_1, hidl_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;
+
+	const std::string ifname(wpa_s->ifname);
+	if (sta_iface_object_map_.find(ifname) == sta_iface_object_map_.end())
+		return;
+
+	std::vector<uint8_t> hidl_image(image, image + image_length);
+	std::array<uint8_t, 6> hidl_bssid;
+	os_memcpy(hidl_bssid.data(), bssid, ETH_ALEN);
+	callWithEachStaIfaceCallback(
+	    wpa_s->ifname,
+	    std::bind(
+		&ISupplicantStaIfaceCallback::onHs20IconQueryDone,
+		std::placeholders::_1, hidl_bssid, file_name, hidl_image));
+}
+
+/**
+ * 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;
+
+	const std::string ifname(wpa_s->ifname);
+	if (sta_iface_object_map_.find(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, 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;
+
+	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::onHs20DeauthImminentNotice,
+		std::placeholders::_1, 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;
+
+	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;
+	}
+	std::array<uint8_t, 6> hidl_bssid;
+	os_memcpy(hidl_bssid.data(), bssid, ETH_ALEN);
+
+	callWithEachStaIfaceCallback(
+	    wpa_s->ifname,
+	    std::bind(
+		&ISupplicantStaIfaceCallback::onDisconnected,
+		std::placeholders::_1, hidl_bssid, wpa_s->disconnect_reason < 0,
+		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;
+
+	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;
+	}
+	std::array<uint8_t, 6> hidl_bssid;
+	os_memcpy(hidl_bssid.data(), bssid, ETH_ALEN);
+
+	callWithEachStaIfaceCallback(
+	    wpa_s->ifname,
+	    std::bind(
+		&ISupplicantStaIfaceCallback::onAssociationRejected,
+		std::placeholders::_1, hidl_bssid, wpa_s->assoc_status_code));
+}
+
+/**
  * 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 5f1c7b6..8c4aa7f 100644
--- a/wpa_supplicant/hidl/hidl_manager.h
+++ b/wpa_supplicant/hidl/hidl_manager.h
@@ -63,6 +63,19 @@
 	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);
 
 	// Methods called from hidl objects.
 	int getP2pIfaceHidlObjectByIfname(
@@ -314,6 +327,88 @@
 	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<uint32_t>(
+	ISupplicantP2pIface::GroupCapabilityMask::GROUP_OWNER) ==
+	P2P_GROUP_CAPAB_GROUP_OWNER,
+    "P2P capability value mismatch");
+static_assert(
+    static_cast<uint32_t>(
+	ISupplicantP2pIface::GroupCapabilityMask::PERSISTENT_GROUP) ==
+	P2P_GROUP_CAPAB_PERSISTENT_GROUP,
+    "P2P capability value mismatch");
+static_assert(
+    static_cast<uint32_t>(
+	ISupplicantP2pIface::GroupCapabilityMask::GROUP_LIMIT) ==
+	P2P_GROUP_CAPAB_GROUP_LIMIT,
+    "P2P capability value mismatch");
+static_assert(
+    static_cast<uint32_t>(
+	ISupplicantP2pIface::GroupCapabilityMask::INTRA_BSS_DIST) ==
+	P2P_GROUP_CAPAB_INTRA_BSS_DIST,
+    "P2P capability value mismatch");
+static_assert(
+    static_cast<uint32_t>(
+	ISupplicantP2pIface::GroupCapabilityMask::CROSS_CONN) ==
+	P2P_GROUP_CAPAB_CROSS_CONN,
+    "P2P capability value mismatch");
+static_assert(
+    static_cast<uint32_t>(
+	ISupplicantP2pIface::GroupCapabilityMask::PERSISTENT_RECONN) ==
+	P2P_GROUP_CAPAB_PERSISTENT_RECONN,
+    "P2P capability value mismatch");
+static_assert(
+    static_cast<uint32_t>(
+	ISupplicantP2pIface::GroupCapabilityMask::GROUP_FORMATION) ==
+	P2P_GROUP_CAPAB_GROUP_FORMATION,
+    "P2P capability value mismatch");
 }  // namespace implementation
 }  // namespace V1_0
 }  // namespace wifi
diff --git a/wpa_supplicant/hidl/p2p_iface.cpp b/wpa_supplicant/hidl/p2p_iface.cpp
index 9c0b3f4..6ad0696 100644
--- a/wpa_supplicant/hidl/p2p_iface.cpp
+++ b/wpa_supplicant/hidl/p2p_iface.cpp
@@ -11,6 +11,12 @@
 #include "hidl_return_util.h"
 #include "p2p_iface.h"
 
+namespace {
+const char kConfigMethodStrPbc[] = "pbc";
+const char kConfigMethodStrDisplay[] = "display";
+const char kConfigMethodStrKeypad[] = "keypad";
+}  // namespace
+
 namespace android {
 namespace hardware {
 namespace wifi {
@@ -90,7 +96,7 @@
 }
 
 Return<void> P2pIface::setSsidPostfix(
-    const hidl_string& postfix, setSsidPostfix_cb _hidl_cb)
+    const hidl_vec<uint8_t>& postfix, setSsidPostfix_cb _hidl_cb)
 {
 	return validateAndCall(
 	    this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
@@ -98,18 +104,21 @@
 }
 
 Return<void> P2pIface::setGroupIdle(
-    uint32_t timeout_in_sec, setGroupIdle_cb _hidl_cb)
+    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, timeout_in_sec);
+	    &P2pIface::setGroupIdleInternal, _hidl_cb, group_ifname,
+	    timeout_in_sec);
 }
 
-Return<void> P2pIface::setPowerSave(bool enable, setPowerSave_cb _hidl_cb)
+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, enable);
+	    &P2pIface::setPowerSaveInternal, _hidl_cb, group_ifname, enable);
 }
 
 Return<void> P2pIface::find(uint32_t timeout_in_sec, find_cb _hidl_cb)
@@ -136,7 +145,7 @@
 Return<void> P2pIface::connect(
     const hidl_array<uint8_t, 6>& peer_address,
     ISupplicantP2pIface::WpsProvisionMethod provision_method,
-    const hidl_vec<uint8_t>& pre_selected_pin, bool join_existing_group,
+    const hidl_string& pre_selected_pin, bool join_existing_group,
     bool persistent, uint32_t go_intent, connect_cb _hidl_cb)
 {
 	return validateAndCall(
@@ -165,7 +174,8 @@
 }
 
 Return<void> P2pIface::addGroup(
-    bool persistent, uint32_t persistent_network_id, addGroup_cb _hidl_cb)
+    bool persistent, SupplicantNetworkId persistent_network_id,
+    addGroup_cb _hidl_cb)
 {
 	return validateAndCall(
 	    this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
@@ -201,8 +211,8 @@
 }
 
 Return<void> P2pIface::reinvoke(
-    uint32_t persistent_network_id, const hidl_array<uint8_t, 6>& peer_address,
-    reinvoke_cb _hidl_cb)
+    SupplicantNetworkId persistent_network_id,
+    const hidl_array<uint8_t, 6>& peer_address, reinvoke_cb _hidl_cb)
 {
 	return validateAndCall(
 	    this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
@@ -229,6 +239,14 @@
 	    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)
 {
@@ -394,59 +412,133 @@
 std::pair<SupplicantStatus, std::array<uint8_t, 6>>
 P2pIface::getDeviceAddressInternal()
 {
-	// TODO: Add implementation.
+	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, ""}, {}};
 }
 
-SupplicantStatus P2pIface::setSsidPostfixInternal(const hidl_string& postfix)
+SupplicantStatus P2pIface::setSsidPostfixInternal(
+    const std::vector<uint8_t>& postfix)
 {
-	// TODO: Add implementation.
+	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(uint32_t timeout_in_sec)
+SupplicantStatus P2pIface::setGroupIdleInternal(
+    const std::string& group_ifname, uint32_t timeout_in_sec)
 {
-	// TODO: Add implementation.
+	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(bool enable)
+SupplicantStatus P2pIface::setPowerSaveInternal(
+    const std::string& group_ifname, bool enable)
 {
-	// TODO: Add implementation.
+	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)
 {
-	// TODO: Add implementation.
+	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()
 {
-	// TODO: Add implementation.
+	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()
 {
-	// TODO: Add implementation.
+	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, ""};
 }
 
-std::pair<SupplicantStatus, std::vector<uint8_t>> P2pIface::connectInternal(
+// 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::vector<uint8_t>& pre_selected_pin, bool join_existing_group,
+    const std::string& pre_selected_pin, bool join_existing_group,
     bool persistent, uint32_t go_intent)
 {
-	// TODO: Add implementation.
-	return {{SupplicantStatusCode::SUCCESS, ""}, {}};
+	struct wpa_supplicant* wpa_s = retrieveIfacePtr();
+	if (go_intent > 15) {
+		return {{SupplicantStatusCode::FAILURE_ARGS_INVALID, ""}, {}};
+	}
+	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 new_pin = wpas_p2p_connect(
+	    wpa_s, peer_address.data(), pre_selected_pin.data(), wps_method,
+	    persistent, false, join_existing_group, false, go_intent, 0, 0, -1,
+	    false, false, false, 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.reserve(9);
+		snprintf(&pin_ret[0], pin_ret.size(), "%08d", new_pin);
+	}
+	return {{SupplicantStatusCode::SUCCESS, ""}, pin_ret};
 }
 
 SupplicantStatus P2pIface::cancelConnectInternal()
 {
-	// TODO: Add implementation.
+	struct wpa_supplicant* wpa_s = retrieveIfacePtr();
+	if (wpas_p2p_cancel(wpa_s)) {
+		return {SupplicantStatusCode::FAILURE_UNKNOWN, ""};
+	}
 	return {SupplicantStatusCode::SUCCESS, ""};
 }
 
@@ -454,106 +546,266 @@
     const std::array<uint8_t, 6>& peer_address,
     ISupplicantP2pIface::WpsProvisionMethod provision_method)
 {
-	// TODO: Add implementation.
+	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, uint32_t persistent_network_id)
+    bool persistent, SupplicantNetworkId persistent_network_id)
 {
-	// TODO: Add implementation.
-	return {SupplicantStatusCode::SUCCESS, ""};
+	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 hidl_string& group_ifname)
+SupplicantStatus P2pIface::removeGroupInternal(const std::string& group_ifname)
 {
-	// TODO: Add implementation.
+	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)
 {
-	// TODO: Add implementation.
+	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 hidl_string& group_ifname,
+    const std::string& group_ifname,
     const std::array<uint8_t, 6>& go_device_address,
     const std::array<uint8_t, 6>& peer_address)
 {
-	// TODO: Add implementation.
+	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(
-    uint32_t persistent_network_id, const std::array<uint8_t, 6>& peer_address)
+    SupplicantNetworkId persistent_network_id,
+    const std::array<uint8_t, 6>& peer_address)
 {
-	// TODO: Add implementation.
+	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(
     bool enable, uint32_t period_in_millis, uint32_t interval_in_millis)
 {
-	// TODO: Add implementation.
+	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)
 {
-	// TODO: Add implementation.
+	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)
+{
+	if (ranges.size() == 0) {
+		return {SupplicantStatusCode::FAILURE_ARGS_INVALID, ""};
+	}
+	struct wpa_supplicant* wpa_s = retrieveIfacePtr();
+	using DestT = struct wpa_freq_range_list::wpa_freq_range;
+	DestT* 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)
 {
-	// TODO: Add implementation.
-	return {{SupplicantStatusCode::SUCCESS, ""}, {}};
+	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)
 {
-	// TODO: Add implementation.
-	return {{SupplicantStatusCode::SUCCESS, ""}, 0};
+	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)
 {
-	// TODO: Add implementation.
+	struct wpa_supplicant* wpa_s = retrieveIfacePtr();
+	struct wpabuf* query_buf = wpabuf_alloc(query.size());
+	if (!query_buf) {
+		return {SupplicantStatusCode::FAILURE_UNKNOWN, ""};
+	}
+	wpabuf_put_data(query_buf, query.data(), query.size());
+
+	struct wpabuf* response_buf = wpabuf_alloc(response.size());
+	if (!query_buf) {
+		wpabuf_free(query_buf);
+		return {SupplicantStatusCode::FAILURE_UNKNOWN, ""};
+	}
+	wpabuf_put_data(response_buf, response.data(), response.size());
+
+	if (wpas_p2p_service_add_bonjour(wpa_s, query_buf, response_buf)) {
+		wpabuf_free(query_buf);
+		wpabuf_free(response_buf);
+		return {SupplicantStatusCode::FAILURE_UNKNOWN, ""};
+	}
 	return {SupplicantStatusCode::SUCCESS, ""};
 }
 
 SupplicantStatus P2pIface::removeBonjourServiceInternal(
     const std::vector<uint8_t>& query)
 {
-	// TODO: Add implementation.
+	struct wpa_supplicant* wpa_s = retrieveIfacePtr();
+	struct wpabuf* query_buf = wpabuf_alloc(query.size());
+	if (!query_buf) {
+		return {SupplicantStatusCode::FAILURE_UNKNOWN, ""};
+	}
+	wpabuf_put_data(query_buf, query.data(), query.size());
+
+	int ret = wpas_p2p_service_del_bonjour(wpa_s, query_buf);
+	wpabuf_free(query_buf);
+	if (ret) {
+		return {SupplicantStatusCode::FAILURE_UNKNOWN, ""};
+	}
 	return {SupplicantStatusCode::SUCCESS, ""};
 }
 
 SupplicantStatus P2pIface::addUpnpServiceInternal(
-    uint32_t version, const hidl_string& service_name)
+    uint32_t version, const std::string& service_name)
 {
-	// TODO: Add implementation.
+	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 hidl_string& service_name)
+    uint32_t version, const std::string& service_name)
 {
-	// TODO: Add implementation.
+	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(
-    uint32_t version, const hidl_string& service_name)
+    uint32_t version, const std::string& service_name)
 {
-	// TODO: Add implementation.
+	struct wpa_supplicant* wpa_s = retrieveIfacePtr();
+	wpas_p2p_service_flush(wpa_s);
 	return {SupplicantStatusCode::SUCCESS, ""};
 }
 
@@ -561,13 +813,27 @@
     const std::array<uint8_t, 6>& peer_address,
     const std::vector<uint8_t>& query)
 {
-	// TODO: Add implementation.
-	return {{SupplicantStatusCode::SUCCESS, ""}, 0};
+	struct wpa_supplicant* wpa_s = retrieveIfacePtr();
+	struct wpabuf* query_buf = wpabuf_alloc(query.size());
+	if (!query_buf) {
+		return {{SupplicantStatusCode::FAILURE_UNKNOWN, ""}, {}};
+	}
+	wpabuf_put_data(query_buf, query.data(), query.size());
+	uint64_t identifier =
+	    wpas_p2p_sd_request(wpa_s, peer_address.data(), query_buf);
+	wpabuf_free(query_buf);
+	if (identifier == 0) {
+		return {{SupplicantStatusCode::FAILURE_UNKNOWN, ""}, {}};
+	}
+	return {{SupplicantStatusCode::SUCCESS, ""}, identifier};
 }
 
 SupplicantStatus P2pIface::cancelServiceDiscoveryInternal(uint64_t identifier)
 {
-	// TODO: Add implementation.
+	struct wpa_supplicant* wpa_s = retrieveIfacePtr();
+	if (wpas_p2p_sd_cancel_request(wpa_s, identifier)) {
+		return {SupplicantStatusCode::FAILURE_UNKNOWN, ""};
+	}
 	return {SupplicantStatusCode::SUCCESS, ""};
 }
 
@@ -579,8 +845,16 @@
  */
 wpa_supplicant* P2pIface::retrieveIfacePtr()
 {
-	return wpa_supplicant_get_iface(
-	    (struct wpa_global*)wpa_global_, ifname_.c_str());
+	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
diff --git a/wpa_supplicant/hidl/p2p_iface.h b/wpa_supplicant/hidl/p2p_iface.h
index d340b08..312b8bb 100644
--- a/wpa_supplicant/hidl/p2p_iface.h
+++ b/wpa_supplicant/hidl/p2p_iface.h
@@ -22,9 +22,11 @@
 extern "C" {
 #include "utils/common.h"
 #include "utils/includes.h"
-#include "wpa_supplicant_i.h"
+#include "p2p/p2p.h"
+#include "p2p/p2p_i.h"
+#include "p2p_supplicant.h"
+#include "p2p_supplicant.h"
 #include "config.h"
-#include "driver_i.h"
 }
 
 namespace android {
@@ -63,18 +65,21 @@
 	    registerCallback_cb _hidl_cb) override;
 	Return<void> getDeviceAddress(getDeviceAddress_cb _hidl_cb) override;
 	Return<void> setSsidPostfix(
-	    const hidl_string& postfix, setSsidPostfix_cb _hidl_cb) override;
+	    const hidl_vec<uint8_t>& postfix,
+	    setSsidPostfix_cb _hidl_cb) override;
 	Return<void> setGroupIdle(
-	    uint32_t timeout_in_sec, setGroupIdle_cb _hidl_cb) override;
+	    const hidl_string& group_ifname, uint32_t timeout_in_sec,
+	    setGroupIdle_cb _hidl_cb) override;
 	Return<void> setPowerSave(
-	    bool enable, setPowerSave_cb _hidl_cb) override;
+	    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_vec<uint8_t>& pre_selected_pin, bool join_existing_group,
+	    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(
@@ -82,7 +87,7 @@
 	    ISupplicantP2pIface::WpsProvisionMethod provision_method,
 	    provisionDiscovery_cb _hidl_cb) override;
 	Return<void> addGroup(
-	    bool persistent, uint32_t persistent_network_id,
+	    bool persistent, SupplicantNetworkId persistent_network_id,
 	    addGroup_cb _hidl_cb) override;
 	Return<void> removeGroup(
 	    const hidl_string& group_ifname, removeGroup_cb _hidl_cb) override;
@@ -95,7 +100,7 @@
 	    const hidl_array<uint8_t, 6>& peer_address,
 	    invite_cb _hidl_cb) override;
 	Return<void> reinvoke(
-	    uint32_t persistent_network_id,
+	    SupplicantNetworkId persistent_network_id,
 	    const hidl_array<uint8_t, 6>& peer_address,
 	    reinvoke_cb _hidl_cb) override;
 	Return<void> configureExtListen(
@@ -104,6 +109,9 @@
 	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;
@@ -147,38 +155,43 @@
 	    const sp<ISupplicantP2pIfaceCallback>& callback);
 	std::pair<SupplicantStatus, std::array<uint8_t, 6>>
 	getDeviceAddressInternal();
-	SupplicantStatus setSsidPostfixInternal(const hidl_string& postfix);
-	SupplicantStatus setGroupIdleInternal(uint32_t timeout_in_sec);
-	SupplicantStatus setPowerSaveInternal(bool enable);
+	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::vector<uint8_t>> connectInternal(
+	std::pair<SupplicantStatus, std::string> connectInternal(
 	    const std::array<uint8_t, 6>& peer_address,
 	    ISupplicantP2pIface::WpsProvisionMethod provision_method,
-	    const std::vector<uint8_t>& pre_selected_pin,
-	    bool join_existing_group, bool persistent, uint32_t go_intent);
+	    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, uint32_t persistent_network_id);
-	SupplicantStatus removeGroupInternal(const hidl_string& group_ifname);
+	    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 hidl_string& group_ifname,
+	    const std::string& group_ifname,
 	    const std::array<uint8_t, 6>& go_device_address,
 	    const std::array<uint8_t, 6>& peer_address);
 	SupplicantStatus reinvokeInternal(
-	    uint32_t persistent_network_id,
+	    SupplicantNetworkId persistent_network_id,
 	    const std::array<uint8_t, 6>& peer_address);
 	SupplicantStatus configureExtListenInternal(
 	    bool enable, 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(
@@ -189,21 +202,23 @@
 	SupplicantStatus removeBonjourServiceInternal(
 	    const std::vector<uint8_t>& query);
 	SupplicantStatus addUpnpServiceInternal(
-	    uint32_t version, const hidl_string& service_name);
+	    uint32_t version, const std::string& service_name);
 	SupplicantStatus removeUpnpServiceInternal(
-	    uint32_t version, const hidl_string& service_name);
+	    uint32_t version, const std::string& service_name);
 	SupplicantStatus flushServicesInternal(
-	    uint32_t version, const hidl_string& service_name);
+	    uint32_t version, const std::string& service_name);
 	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);
 
 	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.
-	const struct wpa_global* wpa_global_;
+	struct wpa_global* wpa_global_;
 	// Name of the iface this hidl object controls
 	const std::string ifname_;
 	bool is_valid_;
diff --git a/wpa_supplicant/hidl/sta_iface.cpp b/wpa_supplicant/hidl/sta_iface.cpp
index 4379dd5..a60267d 100644
--- a/wpa_supplicant/hidl/sta_iface.cpp
+++ b/wpa_supplicant/hidl/sta_iface.cpp
@@ -11,6 +11,16 @@
 #include "hidl_return_util.h"
 #include "sta_iface.h"
 
+extern "C" {
+#include "gas_query.h"
+#include "interworking.h"
+#include "hs20_supplicant.h"
+}
+
+namespace {
+constexpr uint32_t kMaxAnqpElems = 100;
+}  // namespace
+
 namespace android {
 namespace hardware {
 namespace wifi {
@@ -345,14 +355,46 @@
     const std::vector<ISupplicantStaIface::AnqpInfoId> &info_elements,
     const std::vector<ISupplicantStaIface::Hs20AnqpSubtypes> &sub_types)
 {
-	// TODO: Add implementation.
+	struct wpa_supplicant *wpa_s = retrieveIfacePtr();
+	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, ""};
+	}
+	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)
 {
-	// TODO: Add implementation.
+	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, ""};
 }
 
@@ -364,8 +406,7 @@
  */
 wpa_supplicant *StaIface::retrieveIfacePtr()
 {
-	return wpa_supplicant_get_iface(
-	    (struct wpa_global *)wpa_global_, ifname_.c_str());
+	return wpa_supplicant_get_iface(wpa_global_, ifname_.c_str());
 }
 
 }  // namespace implementation
diff --git a/wpa_supplicant/hidl/sta_iface.h b/wpa_supplicant/hidl/sta_iface.h
index a4177aa..01b2b5e 100644
--- a/wpa_supplicant/hidl/sta_iface.h
+++ b/wpa_supplicant/hidl/sta_iface.h
@@ -133,7 +133,7 @@
 
 	// Reference to the global wpa_struct. This is assumed to be valid for
 	// the lifetime of the process.
-	const struct wpa_global* wpa_global_;
+	struct wpa_global* wpa_global_;
 	// Name of the iface this hidl object controls
 	const std::string ifname_;
 	bool is_valid_;
diff --git a/wpa_supplicant/hidl/sta_network.cpp b/wpa_supplicant/hidl/sta_network.cpp
index 15e628f..226c1bd 100644
--- a/wpa_supplicant/hidl/sta_network.cpp
+++ b/wpa_supplicant/hidl/sta_network.cpp
@@ -48,6 +48,8 @@
     static_cast<uint32_t>(ISupplicantStaNetwork::EapPhase2Method::GTC) + 1;
 constexpr char const *kEapPhase2MethodStrings[kEapPhase2MethodMax] = {
     "NULL", "PAP", "MSCHAP", "MSCHAPV2", "GTC"};
+constexpr char kEapPhase2AuthPrefix[] = "auth=";
+constexpr char kEapPhase2AuthEapPrefix[] = "autheap=";
 }  // namespace
 
 namespace android {
@@ -394,6 +396,107 @@
 	    &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::getEapPrivateKey(getEapPrivateKey_cb _hidl_cb)
+{
+	return validateAndCall(
+	    this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
+	    &StaNetwork::getEapPrivateKeyInternal, _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::getEapSubjectMatchInternal, _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::enable(bool no_connect, enable_cb _hidl_cb)
 {
 	return validateAndCall(
@@ -662,10 +765,16 @@
 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[static_cast<uint32_t>(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);
@@ -709,10 +818,34 @@
 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 (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(
-		kEapPhase2MethodStrings[static_cast<uint32_t>(method)],
-		&(wpa_ssid->eap.phase2), "eap phase2")) {
+		eap_phase2_str.c_str(), &(wpa_ssid->eap.phase2),
+		"eap phase2")) {
 		return {SupplicantStatusCode::FAILURE_UNKNOWN, ""};
 	}
 	return {SupplicantStatusCode::SUCCESS, ""};
@@ -950,10 +1083,201 @@
 		(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::getEapPrivateKeyInternal()
+{
+	struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
+	if (!wpa_ssid->eap.private_key) {
+		return {{SupplicantStatusCode::FAILURE_UNKNOWN, ""}, {}};
+	}
+	return {{SupplicantStatusCode::SUCCESS, ""},
+		reinterpret_cast<char *>(wpa_ssid->eap.private_key)};
+}
+
+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}};
+}
+
 SupplicantStatus StaNetwork::enableInternal(bool no_connect)
 {
 	struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
-	if (wpa_ssid->disabled != 0) {
+	if (wpa_ssid->disabled == 2) {
 		return {SupplicantStatusCode::FAILURE_UNKNOWN, ""};
 	}
 	struct wpa_supplicant *wpa_s = retrieveIfacePtr();
@@ -1118,8 +1442,7 @@
  */
 struct wpa_supplicant *StaNetwork::retrieveIfacePtr()
 {
-	return wpa_supplicant_get_iface(
-	    (struct wpa_global *)wpa_global_, ifname_.c_str());
+	return wpa_supplicant_get_iface(wpa_global_, ifname_.c_str());
 }
 
 /**
diff --git a/wpa_supplicant/hidl/sta_network.h b/wpa_supplicant/hidl/sta_network.h
index f35f230..68ab139 100644
--- a/wpa_supplicant/hidl/sta_network.h
+++ b/wpa_supplicant/hidl/sta_network.h
@@ -131,6 +131,25 @@
 	    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> getEapPrivateKey(getEapPrivateKey_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> 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;
@@ -201,6 +220,27 @@
 	    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> getEapPrivateKeyInternal();
+	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();
 	SupplicantStatus enableInternal(bool no_connect);
 	SupplicantStatus disableInternal();
 	SupplicantStatus selectInternal();
@@ -237,7 +277,7 @@
 
 	// Reference to the global wpa_struct. This is assumed to be valid
 	// for the lifetime of the process.
-	const struct wpa_global* wpa_global_;
+	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.
diff --git a/wpa_supplicant/hidl/supplicant.cpp b/wpa_supplicant/hidl/supplicant.cpp
index aba4402..409547f 100644
--- a/wpa_supplicant/hidl/supplicant.cpp
+++ b/wpa_supplicant/hidl/supplicant.cpp
@@ -165,7 +165,15 @@
 
 SupplicantStatus Supplicant::setConcurrencyPriorityInternal(IfaceType type)
 {
-	// TODO: Add implementation.
+	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
diff --git a/wpa_supplicant/hs20_supplicant.c b/wpa_supplicant/hs20_supplicant.c
index e88f147..858636f 100644
--- a/wpa_supplicant/hs20_supplicant.c
+++ b/wpa_supplicant/hs20_supplicant.c
@@ -20,6 +20,7 @@
 #include "driver_i.h"
 #include "config.h"
 #include "scan.h"
+#include "notify.h"
 #include "bss.h"
 #include "blacklist.h"
 #include "gas_query.h"
@@ -439,6 +440,10 @@
 				RX_HS20_ICON MACSTR " %s %u",
 				MAC2STR(sa), icon->file_name,
 				(unsigned int) icon->image_len);
+			wpas_notify_hs20_icon_query_done(wpa_s, sa,
+							 icon->file_name,
+							 icon->image,
+							 icon->image_len);
 			return 0;
 		}
 	}
@@ -1161,6 +1166,7 @@
 			osu_method, url);
 	else
 		wpa_msg(wpa_s, MSG_INFO, HS20_SUBSCRIPTION_REMEDIATION);
+	wpas_notify_hs20_rx_subscription_remediation(wpa_s, url, osu_method);
 }
 
 
@@ -1174,6 +1180,7 @@
 
 	wpa_msg(wpa_s, MSG_INFO, HS20_DEAUTH_IMMINENT_NOTICE "%u %u %s",
 		code, reauth_delay, url);
+	wpas_notify_hs20_rx_deauth_imminent_notice(wpa_s, code, reauth_delay, url);
 
 	if (code == HS20_DEAUTH_REASON_CODE_BSS) {
 		wpa_printf(MSG_DEBUG, "HS 2.0: Add BSS to blacklist");
diff --git a/wpa_supplicant/interworking.c b/wpa_supplicant/interworking.c
index 1fb40c7..d8368aa 100644
--- a/wpa_supplicant/interworking.c
+++ b/wpa_supplicant/interworking.c
@@ -3025,6 +3025,7 @@
 out:
 	wpa_msg(wpa_s, MSG_INFO, ANQP_QUERY_DONE "addr=" MACSTR " result=%s",
 		MAC2STR(dst), anqp_result);
+	wpas_notify_anqp_query_done(wpa_s, dst, anqp_result, bss ? bss->anqp : NULL);
 }
 
 
diff --git a/wpa_supplicant/notify.c b/wpa_supplicant/notify.c
index ba96548..5dac806 100644
--- a/wpa_supplicant/notify.c
+++ b/wpa_supplicant/notify.c
@@ -13,7 +13,6 @@
 #include "config.h"
 #include "wpa_supplicant_i.h"
 #include "wps_supplicant.h"
-#include "hidl/hidl.h"
 #include "dbus/dbus_common.h"
 #include "dbus/dbus_old.h"
 #include "dbus/dbus_new.h"
@@ -24,6 +23,7 @@
 #include "p2p_supplicant.h"
 #include "sme.h"
 #include "notify.h"
+#include "hidl/hidl.h"
 
 int wpas_notify_supplicant_initialized(struct wpa_global *global)
 {
@@ -144,6 +144,8 @@
 		return;
 
 	wpas_dbus_signal_prop_changed(wpa_s, WPAS_DBUS_PROP_DISCONNECT_REASON);
+
+	wpas_hidl_notify_assoc_reject(wpa_s);
 }
 
 
@@ -153,6 +155,8 @@
 		return;
 
 	wpas_dbus_signal_prop_changed(wpa_s, WPAS_DBUS_PROP_ASSOC_STATUS_CODE);
+
+	wpas_hidl_notify_assoc_reject(wpa_s);
 }
 
 
@@ -863,3 +867,53 @@
 	}
 #endif /* CONFIG_P2P */
 }
+
+void wpas_notify_anqp_query_done(struct wpa_supplicant *wpa_s, const u8* bssid,
+				 const char *result,
+				 const struct wpa_bss_anqp *anqp)
+{
+#ifdef CONFIG_INTERWORKING
+	if (!wpa_s || !bssid || !anqp)
+		return;
+
+	wpas_hidl_notify_anqp_query_done(wpa_s, bssid, result, anqp);
+#endif /* CONFIG_INTERWORKING */
+}
+
+void wpas_notify_hs20_icon_query_done(struct wpa_supplicant *wpa_s, const u8* bssid,
+				      const char* file_name, const u8* image,
+				      u32 image_length)
+{
+#ifdef CONFIG_HS20
+	if (!wpa_s || !bssid || !file_name || !image)
+		return;
+
+	wpas_hidl_notify_hs20_icon_query_done(wpa_s, bssid, file_name, image,
+					      image_length);
+#endif /* CONFIG_HS20 */
+}
+
+void wpas_notify_hs20_rx_subscription_remediation(struct wpa_supplicant *wpa_s,
+						  const char* url,
+						  u8 osu_method)
+{
+#ifdef CONFIG_HS20
+	if (!wpa_s || !url)
+		return;
+
+	wpas_hidl_notify_hs20_rx_subscription_remediation(wpa_s, url, osu_method);
+#endif /* CONFIG_HS20 */
+}
+
+void wpas_notify_hs20_rx_deauth_imminent_notice(struct wpa_supplicant *wpa_s,
+						u8 code, u16 reauth_delay,
+						const char *url)
+{
+#ifdef CONFIG_HS20
+	if (!wpa_s || !url)
+		return;
+
+	wpas_hidl_notify_hs20_rx_deauth_imminent_notice(wpa_s, code, reauth_delay,
+							url);
+#endif /* CONFIG_HS20 */
+}
diff --git a/wpa_supplicant/notify.h b/wpa_supplicant/notify.h
index e4d7fbf..2590e9a 100644
--- a/wpa_supplicant/notify.h
+++ b/wpa_supplicant/notify.h
@@ -10,6 +10,7 @@
 #define NOTIFY_H
 
 #include "p2p/p2p.h"
+#include "bss.h"
 
 struct wps_credential;
 struct wps_event_m2d;
@@ -141,5 +142,16 @@
 void wpas_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_notify_anqp_query_done(struct wpa_supplicant *wpa_s, const u8* bssid,
+				 const char* result,
+				 const struct wpa_bss_anqp *anqp);
+void wpas_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_notify_hs20_rx_subscription_remediation(struct wpa_supplicant *wpa_s,
+						  const char* url,
+						  u8 osu_method);
+void wpas_notify_hs20_rx_deauth_imminent_notice(struct wpa_supplicant *wpa_s,
+						u8 code, u16 reauth_delay,
+						const char *url);
 #endif /* NOTIFY_H */