Add callback bridge layer and implement the
onUsdServiceDiscovered callback.

This layer will forward callbacks from the
core supplicant to the registered AIDL
callback objects.

Bug: 365585450
Test: m
Change-Id: I1e6b97c9fc6ffb41630b6f5e5dcca797ee04d54f
diff --git a/wpa_supplicant/aidl/mainline/Android.bp b/wpa_supplicant/aidl/mainline/Android.bp
index a2f5370..43c9c1a 100644
--- a/wpa_supplicant/aidl/mainline/Android.bp
+++ b/wpa_supplicant/aidl/mainline/Android.bp
@@ -31,6 +31,7 @@
         "libbinder_ndk",
     ],
     cppflags: [
+        "-DMAINLINE_SUPPLICANT",
         "-Wall",
         "-Werror",
         "-Wno-unused-parameter",
diff --git a/wpa_supplicant/aidl/mainline/callback_bridge.cpp b/wpa_supplicant/aidl/mainline/callback_bridge.cpp
new file mode 100644
index 0000000..1cf59ec
--- /dev/null
+++ b/wpa_supplicant/aidl/mainline/callback_bridge.cpp
@@ -0,0 +1,32 @@
+/*
+ * WPA Supplicant - Interface to receive callbacks from the core supplicant
+ * Copyright (c) 2025, Google Inc. All rights reserved.
+ *
+ * This software may be distributed under the terms of the BSD license.
+ * See README for more details.
+ */
+
+#include "utils.h"
+#include "usd_utils.h"
+
+extern "C"
+{
+#include "callback_bridge.h"
+}
+
+void mainline_aidl_notify_usd_service_discovered(struct wpa_supplicant *wpa_s,
+        enum nan_service_protocol_type srv_proto_type,
+        int subscribe_id, int peer_publish_id, const u8 *peer_addr,
+        bool fsd, const u8 *ssi, size_t ssi_len) {
+    if (!wpa_s || !peer_addr)
+        return;
+
+    auto callback = getStaIfaceCallback(wpa_s->ifname);
+    if (!callback)
+        return;
+
+    wpa_printf(MSG_DEBUG, "Notifying USD service discovered");
+    auto serviceDiscoveryInfo = createUsdServiceDiscoveryInfo(
+        srv_proto_type, subscribe_id, peer_publish_id, peer_addr, fsd, ssi, ssi_len);
+    callback->onUsdServiceDiscovered(serviceDiscoveryInfo);
+}
diff --git a/wpa_supplicant/aidl/mainline/callback_bridge.h b/wpa_supplicant/aidl/mainline/callback_bridge.h
new file mode 100644
index 0000000..bba0635
--- /dev/null
+++ b/wpa_supplicant/aidl/mainline/callback_bridge.h
@@ -0,0 +1,48 @@
+/*
+ * WPA Supplicant - Interface to receive callbacks from the core supplicant
+ * Copyright (c) 2025, Google Inc. All rights reserved.
+ *
+ * This software may be distributed under the terms of the BSD license.
+ * See README for more details.
+ */
+
+#ifndef MAINLINE_SUPPLICANT_CALLBACK_BRIDGE_H
+#define MAINLINE_SUPPLICANT_CALLBACK_BRIDGE_H
+
+/**
+ * Intermediary layer to receive callbacks from the core supplicant.
+ *
+ * For each callback, we provide a full implementation if the MAINLINE_SUPPLICANT
+ * flag is enabled. Otherwise, we provide an empty default implementation for builds
+ * that do not have the flag enabled (ex. the vendor supplicant).
+ */
+#ifdef _cplusplus
+extern "C"
+{
+#endif  // _cplusplus
+
+#include "utils/common.h"
+#include "src/common/nan_de.h"
+#include "wpa_supplicant_i.h"
+
+#ifdef MAINLINE_SUPPLICANT
+
+void mainline_aidl_notify_usd_service_discovered(struct wpa_supplicant *wpa_s,
+    enum nan_service_protocol_type srv_proto_type,
+    int subscribe_id, int peer_publish_id, const u8 *peer_addr,
+    bool fsd, const u8 *ssi, size_t ssi_len);
+
+#else // MAINLINE_SUPPLICANT
+
+static void mainline_aidl_notify_usd_service_discovered(struct wpa_supplicant *wpa_s,
+    enum nan_service_protocol_type srv_proto_type,
+    int subscribe_id, int peer_publish_id, const u8 *peer_addr,
+    bool fsd, const u8 *ssi, size_t ssi_len) {}
+
+#endif // MAINLINE_SUPPLICANT
+
+#ifdef _cplusplus
+}
+#endif  // _cplusplus
+
+#endif // MAINLINE_SUPPLICANT_CALLBACK_BRIDGE_H
diff --git a/wpa_supplicant/aidl/mainline/usd_utils.h b/wpa_supplicant/aidl/mainline/usd_utils.h
index 428a599..c9ad20a 100644
--- a/wpa_supplicant/aidl/mainline/usd_utils.h
+++ b/wpa_supplicant/aidl/mainline/usd_utils.h
@@ -150,4 +150,34 @@
     };
 }
 
+static UsdServiceProtoType convertInternalUsdServiceProtoTypeToAidl(
+        nan_service_protocol_type protocolType) {
+    switch (protocolType) {
+        case NAN_SRV_PROTO_GENERIC:
+            return UsdServiceProtoType::GENERIC;
+        case NAN_SRV_PROTO_CSA_MATTER:
+            return UsdServiceProtoType::CSA_MATTER;
+        default:
+            wpa_printf(MSG_ERROR, "Received invalid USD proto type %d from internal",
+                static_cast<int>(protocolType));
+            return UsdServiceProtoType::GENERIC;
+    }
+}
+
+static IStaInterfaceCallback::UsdServiceDiscoveryInfo createUsdServiceDiscoveryInfo(
+        enum nan_service_protocol_type srv_proto_type,
+        int own_id, int peer_id, const u8 *peer_addr,
+        bool fsd, const u8 *ssi, size_t ssi_len) {
+    IStaInterfaceCallback::UsdServiceDiscoveryInfo discoveryInfo;
+    discoveryInfo.ownId = own_id;
+    discoveryInfo.peerId = peer_id;
+    // TODO: Fill the matchFilter field in the AIDL struct
+    discoveryInfo.matchFilter = std::vector<uint8_t>();
+    discoveryInfo.peerMacAddress = macAddrBytesToArray(peer_addr);
+    discoveryInfo.serviceProtoType = convertInternalUsdServiceProtoTypeToAidl(srv_proto_type);
+    discoveryInfo.serviceSpecificInfo = ssi ? byteArrToVec(ssi, ssi_len) : std::vector<uint8_t>();
+    discoveryInfo.isFsd = fsd;
+    return discoveryInfo;
+}
+
 #endif // MAINLINE_SUPPLICANT_USD_UTILS_H
diff --git a/wpa_supplicant/aidl/mainline/utils.h b/wpa_supplicant/aidl/mainline/utils.h
index 8b1fd19..bf7b9fb 100644
--- a/wpa_supplicant/aidl/mainline/utils.h
+++ b/wpa_supplicant/aidl/mainline/utils.h
@@ -9,6 +9,8 @@
 #ifndef MAINLINE_SUPPLICANT_UTILS_H
 #define MAINLINE_SUPPLICANT_UTILS_H
 
+#include "callback_manager.h"
+
 #include <aidl/android/system/wifi/mainline_supplicant/SupplicantStatusCode.h>
 
 extern "C"
@@ -60,4 +62,26 @@
     return createWpaBufUniquePtr(wpabuf_alloc_copy(data.data(), data.size()));
 }
 
+// Convert a byte array representation of a MAC address to an std::array
+inline std::array<uint8_t, ETH_ALEN> macAddrBytesToArray(const uint8_t* mac_addr) {
+    std::array<uint8_t, ETH_ALEN> arr;
+    std::copy(mac_addr, mac_addr + ETH_ALEN, std::begin(arr));
+    return arr;
+}
+
+// Convert a byte array to an std::vector
+inline std::vector<uint8_t> byteArrToVec(const uint8_t* arr, int len) {
+    return std::vector<uint8_t>{arr, arr + len};
+}
+
+// Wrapper to retrieve a STA iface callback registered with the callback manager
+static std::shared_ptr<IStaInterfaceCallback> getStaIfaceCallback(
+        std::string ifaceName) {
+    CallbackManager* callback_manager = CallbackManager::getInstance();
+    if (!callback_manager) {
+        return nullptr;
+    }
+    return callback_manager->getStaIfaceCallback(ifaceName);
+}
+
 #endif // MAINLINE_SUPPLICANT_UTILS_H
diff --git a/wpa_supplicant/notify.c b/wpa_supplicant/notify.c
index d5a34c5..123cb44 100644
--- a/wpa_supplicant/notify.c
+++ b/wpa_supplicant/notify.c
@@ -27,6 +27,7 @@
 #include "sme.h"
 #include "notify.h"
 #include "aidl/vendor/aidl.h"
+#include "aidl/mainline/callback_bridge.h"
 
 #ifdef MAINLINE_SUPPLICANT
 #include "aidl/mainline/service.h"
@@ -1533,6 +1534,8 @@
 
 	wpas_aidl_notify_usd_service_discovered(wpa_s, srv_proto_type,
 		subscribe_id, peer_publish_id, peer_addr, fsd, ssi, ssi_len);
+	mainline_aidl_notify_usd_service_discovered(wpa_s, srv_proto_type,
+		subscribe_id, peer_publish_id, peer_addr, fsd, ssi, ssi_len);
 
 	wpas_dbus_signal_nan_discovery_result(wpa_s, srv_proto_type,
 					      subscribe_id, peer_publish_id,