Merge "Support for sending BTM request frame to upper layer"
diff --git a/src/utils/list.h b/src/utils/list.h
index 85aa5e3..5298c26 100644
--- a/src/utils/list.h
+++ b/src/utils/list.h
@@ -46,12 +46,12 @@
 	item->prev = NULL;
 }
 
-static inline int dl_list_empty(struct dl_list *list)
+static inline int dl_list_empty(const struct dl_list *list)
 {
 	return list->next == list;
 }
 
-static inline unsigned int dl_list_len(struct dl_list *list)
+static inline unsigned int dl_list_len(const struct dl_list *list)
 {
 	struct dl_list *item;
 	int count = 0;
diff --git a/wpa_supplicant/android.config b/wpa_supplicant/android.config
index 5f8c8f6..b11e371 100644
--- a/wpa_supplicant/android.config
+++ b/wpa_supplicant/android.config
@@ -556,4 +556,7 @@
 # be completely removed in a future release.
 CONFIG_WEP=y
 
+# WPA3-Personal (SAE) PK (Public Key) mode
+CONFIG_SAE_PK=y
+
 include $(wildcard $(LOCAL_PATH)/android_config_*.inc)
diff --git a/wpa_supplicant/hidl/1.4/hidl_manager.cpp b/wpa_supplicant/hidl/1.4/hidl_manager.cpp
index d7136a6..8325311 100644
--- a/wpa_supplicant/hidl/1.4/hidl_manager.cpp
+++ b/wpa_supplicant/hidl/1.4/hidl_manager.cpp
@@ -17,6 +17,7 @@
 extern "C" {
 #include "scan.h"
 #include "src/eap_common/eap_sim_common.h"
+#include "list.h"
 }
 
 namespace {
@@ -821,23 +822,33 @@
 	    sta_iface_object_map_.end())
 		return;
 
-	ISupplicantStaIfaceCallback::AnqpData hidl_anqp_data;
+	V1_4::ISupplicantStaIfaceCallback::AnqpData hidl_anqp_data;
 	ISupplicantStaIfaceCallback::Hs20AnqpData hidl_hs20_anqp_data;
 	if (std::string(result) == "SUCCESS") {
-		hidl_anqp_data.venueName =
+		hidl_anqp_data.V1_0.venueName =
 		    misc_utils::convertWpaBufToVector(anqp->venue_name);
-		hidl_anqp_data.roamingConsortium =
+		hidl_anqp_data.V1_0.roamingConsortium =
 		    misc_utils::convertWpaBufToVector(anqp->roaming_consortium);
-		hidl_anqp_data.ipAddrTypeAvailability =
+		hidl_anqp_data.V1_0.ipAddrTypeAvailability =
 		    misc_utils::convertWpaBufToVector(
 			anqp->ip_addr_type_availability);
-		hidl_anqp_data.naiRealm =
+		hidl_anqp_data.V1_0.naiRealm =
 		    misc_utils::convertWpaBufToVector(anqp->nai_realm);
-		hidl_anqp_data.anqp3gppCellularNetwork =
+		hidl_anqp_data.V1_0.anqp3gppCellularNetwork =
 		    misc_utils::convertWpaBufToVector(anqp->anqp_3gpp);
-		hidl_anqp_data.domainName =
+		hidl_anqp_data.V1_0.domainName =
 		    misc_utils::convertWpaBufToVector(anqp->domain_name);
 
+		struct wpa_bss_anqp_elem *elem;
+		dl_list_for_each(elem, &anqp->anqp_elems, struct wpa_bss_anqp_elem,
+				 list) {
+			if (elem->infoid == ANQP_VENUE_URL) {
+				hidl_anqp_data.venueUrl =
+						    misc_utils::convertWpaBufToVector(elem->payload);
+				break;
+			}
+		}
+
 		hidl_hs20_anqp_data.operatorFriendlyName =
 		    misc_utils::convertWpaBufToVector(
 			anqp->hs20_operator_friendly_name);
@@ -851,9 +862,9 @@
 			anqp->hs20_osu_providers_list);
 	}
 
-	callWithEachStaIfaceCallback(
+	callWithEachStaIfaceCallback_1_4(
 	    wpa_s->ifname, std::bind(
-			       &ISupplicantStaIfaceCallback::onAnqpQueryDone,
+			       &V1_4::ISupplicantStaIfaceCallback::onAnqpQueryDone_1_4,
 			       std::placeholders::_1, bssid, hidl_anqp_data,
 			       hidl_hs20_anqp_data));
 }
diff --git a/wpa_supplicant/hidl/1.4/hidl_manager.h b/wpa_supplicant/hidl/1.4/hidl_manager.h
index e3d6312..f027676 100644
--- a/wpa_supplicant/hidl/1.4/hidl_manager.h
+++ b/wpa_supplicant/hidl/1.4/hidl_manager.h
@@ -16,7 +16,7 @@
 #include <android/hardware/wifi/supplicant/1.0/ISupplicantCallback.h>
 #include <android/hardware/wifi/supplicant/1.0/ISupplicantP2pIfaceCallback.h>
 #include <android/hardware/wifi/supplicant/1.0/ISupplicantP2pNetworkCallback.h>
-#include <android/hardware/wifi/supplicant/1.0/ISupplicantStaIfaceCallback.h>
+#include <android/hardware/wifi/supplicant/1.4/ISupplicantStaIfaceCallback.h>
 #include <android/hardware/wifi/supplicant/1.0/ISupplicantStaNetworkCallback.h>
 #include <android/hardware/wifi/supplicant/1.4/ISupplicantStaNetworkCallback.h>
 
diff --git a/wpa_supplicant/hidl/1.4/sta_iface.cpp b/wpa_supplicant/hidl/1.4/sta_iface.cpp
index 1eb36cf..7aa5ebf 100644
--- a/wpa_supplicant/hidl/1.4/sta_iface.cpp
+++ b/wpa_supplicant/hidl/1.4/sta_iface.cpp
@@ -402,7 +402,7 @@
 }
 Return<void> StaIface::initiateAnqpQuery(
     const hidl_array<uint8_t, 6> &mac_address,
-    const hidl_vec<ISupplicantStaIface::AnqpInfoId> &info_elements,
+    const hidl_vec<V1_0::ISupplicantStaIface::AnqpInfoId> &info_elements,
     const hidl_vec<ISupplicantStaIface::Hs20AnqpSubtypes> &sub_types,
     initiateAnqpQuery_cb _hidl_cb)
 {
@@ -412,6 +412,15 @@
 	    info_elements, sub_types);
 }
 
+Return<void> StaIface::initiateVenueUrlAnqpQuery(
+    const hidl_array<uint8_t, 6> &mac_address,
+	initiateVenueUrlAnqpQuery_cb _hidl_cb)
+{
+	return validateAndCall(
+	    this, V1_4::SupplicantStatusCode::FAILURE_IFACE_INVALID,
+	    &StaIface::initiateVenueUrlAnqpQueryInternal, _hidl_cb, mac_address);
+}
+
 Return<void> StaIface::initiateHs20IconQuery(
     const hidl_array<uint8_t, 6> &mac_address, const hidl_string &file_name,
     initiateHs20IconQuery_cb _hidl_cb)
@@ -683,6 +692,14 @@
 	    &StaIface::getWpaDriverCapabilitiesInternal, _hidl_cb);
 }
 
+Return<void> StaIface::getWpaDriverCapabilities_1_4(
+		getWpaDriverCapabilities_1_4_cb _hidl_cb)
+{
+	return validateAndCall(
+	    this, V1_4::SupplicantStatusCode::FAILURE_UNKNOWN,
+	    &StaIface::getWpaDriverCapabilitiesInternal_1_4, _hidl_cb);
+}
+
 Return<void> StaIface::setMboCellularDataStatus(bool available,
 		setMboCellularDataStatus_cb _hidl_cb)
 {
@@ -978,6 +995,19 @@
 	return {SupplicantStatusCode::SUCCESS, ""};
 }
 
+V1_4::SupplicantStatus StaIface::initiateVenueUrlAnqpQueryInternal(
+    const std::array<uint8_t, 6> &mac_address)
+{
+	struct wpa_supplicant *wpa_s = retrieveIfacePtr();
+	uint16_t info_elems_buf[1] = {ANQP_VENUE_URL};
+
+	if (anqp_send_req(
+		wpa_s, mac_address.data(), 0, info_elems_buf, 1, 0, 0)) {
+		return {V1_4::SupplicantStatusCode::FAILURE_UNKNOWN, ""};
+	}
+	return {V1_4::SupplicantStatusCode::SUCCESS, ""};
+}
+
 SupplicantStatus StaIface::initiateHs20IconQueryInternal(
     const std::array<uint8_t, 6> &mac_address, const std::string &file_name)
 {
@@ -1513,6 +1543,12 @@
 std::pair<SupplicantStatus, uint32_t>
 StaIface::getWpaDriverCapabilitiesInternal()
 {
+	return {{SupplicantStatusCode::FAILURE_UNKNOWN, "deprecated"}, 0};
+}
+
+std::pair<V1_4::SupplicantStatus, uint32_t>
+StaIface::getWpaDriverCapabilitiesInternal_1_4()
+{
 	struct wpa_supplicant *wpa_s = retrieveIfacePtr();
 	uint32_t mask = 0;
 
@@ -1526,10 +1562,13 @@
 		mask |= V1_3::WpaDriverCapabilitiesMask::OCE;
 	}
 #endif
+#ifdef CONFIG_SAE_PK
+	mask |= V1_4::WpaDriverCapabilitiesMask::SAE_PK;
+#endif
 
 	wpa_printf(MSG_DEBUG, "Driver capability mask: 0x%x", mask);
 
-	return {{SupplicantStatusCode::SUCCESS, ""}, mask};
+	return {{V1_4::SupplicantStatusCode::SUCCESS, ""}, mask};
 }
 
 SupplicantStatus StaIface::setMboCellularDataStatusInternal(bool available)
diff --git a/wpa_supplicant/hidl/1.4/sta_iface.h b/wpa_supplicant/hidl/1.4/sta_iface.h
index b6590d3..bb5344b 100644
--- a/wpa_supplicant/hidl/1.4/sta_iface.h
+++ b/wpa_supplicant/hidl/1.4/sta_iface.h
@@ -109,9 +109,12 @@
 	    initiateTdlsTeardown_cb _hidl_cb) override;
 	Return<void> initiateAnqpQuery(
 	    const hidl_array<uint8_t, 6>& mac_address,
-	    const hidl_vec<ISupplicantStaIface::AnqpInfoId>& info_elements,
+	    const hidl_vec<V1_0::ISupplicantStaIface::AnqpInfoId>& info_elements,
 	    const hidl_vec<ISupplicantStaIface::Hs20AnqpSubtypes>& sub_types,
 	    initiateAnqpQuery_cb _hidl_cb) override;
+	Return<void> initiateVenueUrlAnqpQuery(
+	    const hidl_array<uint8_t, 6>& mac_address,
+		initiateVenueUrlAnqpQuery_cb _hidl_cb) override;
 	Return<void> initiateHs20IconQuery(
 	    const hidl_array<uint8_t, 6>& mac_address,
 	    const hidl_string& file_name,
@@ -200,6 +203,8 @@
 	    setMboCellularDataStatus_cb _hidl_cb) override;
 	Return<void> getKeyMgmtCapabilities_1_3(
 	    getKeyMgmtCapabilities_1_3_cb _hidl_cb) override;
+	Return<void> getWpaDriverCapabilities_1_4(
+	    getWpaDriverCapabilities_1_4_cb _hidl_cb) override;
 
 private:
 	// Corresponding worker functions for the HIDL methods.
@@ -237,6 +242,8 @@
 	    const std::vector<ISupplicantStaIface::AnqpInfoId>& info_elements,
 	    const std::vector<ISupplicantStaIface::Hs20AnqpSubtypes>&
 		sub_types);
+	V1_4::SupplicantStatus initiateVenueUrlAnqpQueryInternal(
+	    const std::array<uint8_t, 6>& mac_address);
 	SupplicantStatus initiateHs20IconQueryInternal(
 	    const std::array<uint8_t, 6>& mac_address,
 	    const std::string& file_name);
@@ -295,6 +302,7 @@
 	std::pair<SupplicantStatus, uint32_t> getWpaDriverCapabilitiesInternal();
 	SupplicantStatus setMboCellularDataStatusInternal(bool available);
 	std::pair<SupplicantStatus, uint32_t> getKeyMgmtCapabilitiesInternal_1_3();
+	std::pair<V1_4::SupplicantStatus, uint32_t> getWpaDriverCapabilitiesInternal_1_4();
 
 	struct wpa_supplicant* retrieveIfacePtr();
 
diff --git a/wpa_supplicant/hidl/1.4/sta_network.cpp b/wpa_supplicant/hidl/1.4/sta_network.cpp
index d62fdae..6d53282 100644
--- a/wpa_supplicant/hidl/1.4/sta_network.cpp
+++ b/wpa_supplicant/hidl/1.4/sta_network.cpp
@@ -997,6 +997,13 @@
 	    &StaNetwork::enableSaeH2eOnlyModeInternal, _hidl_cb, enable);
 }
 
+Return<void> StaNetwork::enableSaePkOnlyMode(bool enable, enableSaePkOnlyMode_cb _hidl_cb)
+{
+	return validateAndCall(
+	    this, V1_4::SupplicantStatusCode::FAILURE_NETWORK_INVALID,
+	    &StaNetwork::enableSaePkOnlyModeInternal, _hidl_cb, enable);
+}
+
 std::pair<SupplicantStatus, uint32_t> StaNetwork::getIdInternal()
 {
 	return {{SupplicantStatusCode::SUCCESS, ""}, network_id_};
@@ -2616,6 +2623,18 @@
 	return {V1_4::SupplicantStatusCode::SUCCESS, ""};
 }
 
+V1_4::SupplicantStatus StaNetwork::enableSaePkOnlyModeInternal(bool enable)
+{
+#ifdef CONFIG_SAE_PK
+	struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
+	wpa_ssid->sae_pk = enable ? SAE_PK_MODE_ONLY : SAE_PK_MODE_AUTOMATIC;
+	resetInternalStateAfterParamsUpdate();
+	return {V1_4::SupplicantStatusCode::SUCCESS, ""};
+#else
+	return {V1_4::SupplicantStatusCode::FAILURE_UNSUPPORTED, ""};
+#endif
+}
+
 }  // namespace implementation
 }  // namespace V1_4
 }  // namespace supplicant
diff --git a/wpa_supplicant/hidl/1.4/sta_network.h b/wpa_supplicant/hidl/1.4/sta_network.h
index b00f8e5..48bf77b 100644
--- a/wpa_supplicant/hidl/1.4/sta_network.h
+++ b/wpa_supplicant/hidl/1.4/sta_network.h
@@ -272,6 +272,7 @@
 	Return<void> getGroupCipher_1_4(
 	    getGroupCipher_1_4_cb _hidl_cb) override;
 	Return<void> enableSaeH2eOnlyMode(bool enable, enableSaeH2eOnlyMode_cb _hidl_cb) override;
+	Return<void> enableSaePkOnlyMode(bool enable, enableSaePkOnlyMode_cb _hidl_cb) override;
 
 private:
 	// Corresponding worker functions for the HIDL methods.
@@ -414,6 +415,7 @@
 	V1_4::SupplicantStatus setPairwiseCipher_1_4Internal(
 	    uint32_t pairwise_cipher_mask);
 	V1_4::SupplicantStatus enableSaeH2eOnlyModeInternal(bool enable);
+	V1_4::SupplicantStatus enableSaePkOnlyModeInternal(bool enable);
 
 	struct wpa_ssid* retrieveNetworkPtr();
 	struct wpa_supplicant* retrieveIfacePtr();
diff --git a/wpa_supplicant/interworking.c b/wpa_supplicant/interworking.c
index c799b5a..3946252 100644
--- a/wpa_supplicant/interworking.c
+++ b/wpa_supplicant/interworking.c
@@ -2998,13 +2998,13 @@
 	case ANQP_VENUE_URL:
 		wpa_msg(wpa_s, MSG_INFO, RX_ANQP MACSTR " Venue URL",
 			MAC2STR(sa));
-		anqp_add_extra(wpa_s, anqp, info_id, pos, slen);
 
 		if (!pmf_in_use(wpa_s, sa)) {
 			wpa_printf(MSG_DEBUG,
 				   "ANQP: Ignore Venue URL since PMF was not enabled");
 			break;
 		}
+		anqp_add_extra(wpa_s, anqp, info_id, pos, slen);
 		interworking_parse_venue_url(wpa_s, pos, slen);
 		break;
 	case ANQP_VENDOR_SPECIFIC:
diff --git a/wpa_supplicant/wpa_supplicant.c b/wpa_supplicant/wpa_supplicant.c
index 67fb426..6ab5485 100644
--- a/wpa_supplicant/wpa_supplicant.c
+++ b/wpa_supplicant/wpa_supplicant.c
@@ -3844,6 +3844,8 @@
 			 * succeed.
 			 */
 			wpas_connection_failed(wpa_s, wpa_s->pending_bssid);
+			wpa_s->assoc_status_code = WLAN_STATUS_UNSPECIFIED_FAILURE;
+			wpas_notify_assoc_status_code(wpa_s, wpa_s->pending_bssid, 0);
 			wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
 			os_memset(wpa_s->pending_bssid, 0, ETH_ALEN);
 			return;