wpa_supplicant(hidl): Implement ANQP query requests

These will only initiate the ANQP query requests. The callbacks for
these will need some changes in the wpa_supplicant core and will be made
in a separate CL.

Bug: 31116047
Test: Compiles
Change-Id: Ia2d2b4d99da5eefe476748192280f35733174861
diff --git a/wpa_supplicant/hidl/hidl_manager.h b/wpa_supplicant/hidl/hidl_manager.h
index 9acaa00..0b569e2 100644
--- a/wpa_supplicant/hidl/hidl_manager.h
+++ b/wpa_supplicant/hidl/hidl_manager.h
@@ -315,6 +315,53 @@
     "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,
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_;