wpa_supplicant(hidl): Invoke ANQP callbacks

Invoke the corresponding HIDL callbacks for ANQP events.

Bug: 31116047
Test: Compiles
Change-Id: Id5e3e49b0d7369ad4af9950b3ef8270c87baebeb
diff --git a/wpa_supplicant/hidl/hidl.cpp b/wpa_supplicant/hidl/hidl.cpp
index 599938d..55a541e 100644
--- a/wpa_supplicant/hidl/hidl.cpp
+++ b/wpa_supplicant/hidl/hidl.cpp
@@ -181,3 +181,80 @@
 	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);
+}
diff --git a/wpa_supplicant/hidl/hidl.h b/wpa_supplicant/hidl/hidl.h
index ee7cab1..598120f 100644
--- a/wpa_supplicant/hidl/hidl.h
+++ b/wpa_supplicant/hidl/hidl.h
@@ -36,6 +36,16 @@
 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);
 #else   // CONFIG_CTRL_IFACE_HIDL
 static inline int wpas_hidl_register_interface(struct wpa_supplicant *wpa_s)
 {
@@ -65,6 +75,24 @@
 {
 	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)
+{
+}
 #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..8dc3ef5 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,149 @@
 }
 
 /**
+ * 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));
+}
+
+/**
  * 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 0b569e2..468c16a 100644
--- a/wpa_supplicant/hidl/hidl_manager.h
+++ b/wpa_supplicant/hidl/hidl_manager.h
@@ -63,6 +63,17 @@
 	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);
 
 	// Methods called from hidl objects.
 	int getP2pIfaceHidlObjectByIfname(
diff --git a/wpa_supplicant/notify.c b/wpa_supplicant/notify.c
index 9e702f0..abe6353 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)
 {
@@ -871,6 +871,8 @@
 #ifdef CONFIG_INTERWORKING
 	if (!wpa_s || !bssid || !anqp)
 		return;
+
+	wpas_hidl_notify_anqp_query_done(wpa_s, bssid, result, anqp);
 #endif /* CONFIG_INTERWORKING */
 }
 
@@ -881,6 +883,9 @@
 #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 */
 }
 
@@ -891,6 +896,8 @@
 #ifdef CONFIG_HS20
 	if (!wpa_s || !url)
 		return;
+
+	wpas_hidl_notify_hs20_rx_subscription_remediation(wpa_s, url, osu_method);
 #endif /* CONFIG_HS20 */
 }
 
@@ -901,5 +908,8 @@
 #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 */
 }