Merge changes I0867f694,I27481100,If5bc36c6,Iddc76053,Idc34f47b, ... into main

* changes:
  Implement the USD callbacks in aidl_manager.
  Setup USD callback infrastructure and function calls.
  Implement remaining USD methods in the Vendor Supplicant.
  Implement startUsdSubscribe in the Vendor Supplicant.
  Implement startUsdPublish in the Vendor Supplicant.
  Add temporary default implementation for the USD methods.
diff --git a/wpa_supplicant/Android.bp b/wpa_supplicant/Android.bp
index 4bed89c..f2fb64f 100644
--- a/wpa_supplicant/Android.bp
+++ b/wpa_supplicant/Android.bp
@@ -1307,6 +1307,7 @@
         "wpa_supplicant_srcs_default",
         "wpa_supplicant_cflags_default",
         "wpa_supplicant_includes_default",
+        "wpa_supplicant_usd_defaults",
     ],
     soong_config_variables: {
         board_wpa_supplicant_private_lib: {
diff --git a/wpa_supplicant/aidl/vendor/aidl.cpp b/wpa_supplicant/aidl/vendor/aidl.cpp
index a0446fe..afda33f 100644
--- a/wpa_supplicant/aidl/vendor/aidl.cpp
+++ b/wpa_supplicant/aidl/vendor/aidl.cpp
@@ -1116,3 +1116,81 @@
 	wpa_printf(MSG_DEBUG, "Notifying Qos Policy SCS Response");
 	aidl_manager->notifyQosPolicyScsResponse(wpa_s, count, scs_resp);
 }
+
+void wpas_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 || !ssi)
+		return;
+
+	AidlManager *aidl_manager = AidlManager::getInstance();
+	if (!aidl_manager)
+		return;
+
+	wpa_printf(MSG_DEBUG, "Notifying USD service discovered");
+	aidl_manager->notifyUsdServiceDiscovered(wpa_s, srv_proto_type,
+		subscribe_id, peer_publish_id, peer_addr, fsd, ssi, ssi_len);
+}
+
+void wpas_aidl_notify_usd_publish_replied(struct wpa_supplicant *wpa_s,
+		enum nan_service_protocol_type srv_proto_type,
+		int publish_id, int peer_subscribe_id,
+		const u8 *peer_addr, const u8 *ssi, size_t ssi_len)
+{
+	if (!wpa_s || !peer_addr || !ssi)
+		return;
+
+	AidlManager *aidl_manager = AidlManager::getInstance();
+	if (!aidl_manager)
+		return;
+
+	wpa_printf(MSG_DEBUG, "Notifying USD publish replied");
+	aidl_manager->notifyUsdPublishReplied(wpa_s, srv_proto_type,
+		publish_id, peer_subscribe_id, peer_addr, ssi, ssi_len);
+}
+
+void wpas_aidl_notify_usd_message_received(struct wpa_supplicant *wpa_s,
+		int id, int peer_instance_id, const u8 *peer_addr,
+		const u8 *message, size_t message_len)
+{
+	if (!wpa_s || !peer_addr || !message)
+		return;
+
+	AidlManager *aidl_manager = AidlManager::getInstance();
+	if (!aidl_manager)
+		return;
+
+	wpa_printf(MSG_DEBUG, "Notifying USD message received");
+	aidl_manager->notifyUsdMessageReceived(wpa_s, id, peer_instance_id,
+		peer_addr, message, message_len);
+}
+
+void wpas_aidl_notify_usd_publish_terminated(struct wpa_supplicant *wpa_s,
+		int publish_id, enum nan_de_reason reason)
+{
+	if (!wpa_s)
+		return;
+
+	AidlManager *aidl_manager = AidlManager::getInstance();
+	if (!aidl_manager)
+		return;
+
+	wpa_printf(MSG_DEBUG, "Notifying USD publish terminated");
+	aidl_manager->notifyUsdPublishTerminated(wpa_s, publish_id, reason);
+}
+
+void wpas_aidl_notify_usd_subscribe_terminated(struct wpa_supplicant *wpa_s,
+		int subscribe_id, enum nan_de_reason reason)
+{
+	if (!wpa_s)
+		return;
+
+	AidlManager *aidl_manager = AidlManager::getInstance();
+	if (!aidl_manager)
+		return;
+
+	wpa_printf(MSG_DEBUG, "Notifying USD subscribe terminated");
+	aidl_manager->notifyUsdSubscribeTerminated(wpa_s, subscribe_id, reason);
+}
diff --git a/wpa_supplicant/aidl/vendor/aidl.h b/wpa_supplicant/aidl/vendor/aidl.h
index 71620f4..a8f38cb 100644
--- a/wpa_supplicant/aidl/vendor/aidl.h
+++ b/wpa_supplicant/aidl/vendor/aidl.h
@@ -157,6 +157,21 @@
 	ssize_t wpas_aidl_list_aliases(const char *prefix, char ***aliases);
 	void wpas_aidl_notify_qos_policy_scs_response(struct wpa_supplicant *wpa_s,
 		unsigned int count, int **scs_resp);
+	void wpas_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);
+	void wpas_aidl_notify_usd_publish_replied(struct wpa_supplicant *wpa_s,
+		enum nan_service_protocol_type srv_proto_type,
+		int publish_id, int peer_subscribe_id,
+		const u8 *peer_addr, const u8 *ssi, size_t ssi_len);
+	void wpas_aidl_notify_usd_message_received(struct wpa_supplicant *wpa_s, int id,
+		int peer_instance_id, const u8 *peer_addr,
+		const u8 *message, size_t message_len);
+	void wpas_aidl_notify_usd_publish_terminated(struct wpa_supplicant *wpa_s,
+		int publish_id, enum nan_de_reason reason);
+	void wpas_aidl_notify_usd_subscribe_terminated(struct wpa_supplicant *wpa_s,
+		int subscribe_id, enum nan_de_reason reason);
 #else   // CONFIG_CTRL_IFACE_AIDL
 static inline int wpas_aidl_register_interface(struct wpa_supplicant *wpa_s)
 {
@@ -357,6 +372,21 @@
 }
 static void wpas_aidl_notify_qos_policy_scs_response(struct wpa_supplicant *wpa_s,
 	unsigned int count, int **scs_resp) {}
+static void wpas_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) {}
+static void wpas_aidl_notify_usd_publish_replied(struct wpa_supplicant *wpa_s,
+		enum nan_service_protocol_type srv_proto_type,
+		int publish_id, int peer_subscribe_id,
+		const u8 *peer_addr, const u8 *ssi, size_t ssi_len) {}
+static void wpas_aidl_notify_usd_message_received(struct wpa_supplicant *wpa_s, int id,
+		int peer_instance_id, const u8 *peer_addr,
+		const u8 *message, size_t message_len) {}
+static void wpas_aidl_notify_usd_publish_terminated(struct wpa_supplicant *wpa_s,
+		int publish_id, enum nan_de_reason reason) {}
+static void wpas_aidl_notify_usd_subscribe_terminated(struct wpa_supplicant *wpa_s,
+		int subscribe_id, enum nan_de_reason reason) {}
 #endif  // CONFIG_CTRL_IFACE_AIDL
 
 #ifdef _cplusplus
diff --git a/wpa_supplicant/aidl/vendor/aidl_manager.cpp b/wpa_supplicant/aidl/vendor/aidl_manager.cpp
index 177f478..89a4251 100644
--- a/wpa_supplicant/aidl/vendor/aidl_manager.cpp
+++ b/wpa_supplicant/aidl/vendor/aidl_manager.cpp
@@ -2976,6 +2976,162 @@
 			std::placeholders::_1, scsResponses));
 }
 
+void AidlManager::notifyUsdPublishStarted(struct wpa_supplicant *wpa_s,
+		int cmd_id, int publish_id)
+{
+	if (!wpa_s) return;
+	if (!areAidlServiceAndClientAtLeastVersion(4)) return;
+	callWithEachStaIfaceCallback(
+		misc_utils::charBufToString(wpa_s->ifname), std::bind(
+			&ISupplicantStaIfaceCallback::onUsdPublishStarted,
+			std::placeholders::_1, cmd_id, publish_id));
+}
+void AidlManager::notifyUsdSubscribeStarted(struct wpa_supplicant *wpa_s,
+		int cmd_id, int subscribe_id)
+{
+	if (!wpa_s) return;
+	if (!areAidlServiceAndClientAtLeastVersion(4)) return;
+	callWithEachStaIfaceCallback(
+		misc_utils::charBufToString(wpa_s->ifname), std::bind(
+			&ISupplicantStaIfaceCallback::onUsdSubscribeStarted,
+			std::placeholders::_1, cmd_id, subscribe_id));
+}
+void AidlManager::notifyUsdPublishConfigFailed(struct wpa_supplicant *wpa_s, int cmd_id)
+{
+	if (!wpa_s) return;
+	if (!areAidlServiceAndClientAtLeastVersion(4)) return;
+	callWithEachStaIfaceCallback(
+		misc_utils::charBufToString(wpa_s->ifname), std::bind(
+			&ISupplicantStaIfaceCallback::onUsdPublishConfigFailed,
+			std::placeholders::_1, cmd_id));
+}
+
+void AidlManager::notifyUsdSubscribeConfigFailed(struct wpa_supplicant *wpa_s, int cmd_id)
+{
+	if (!wpa_s) return;
+	if (!areAidlServiceAndClientAtLeastVersion(4)) return;
+	callWithEachStaIfaceCallback(
+		misc_utils::charBufToString(wpa_s->ifname), std::bind(
+			&ISupplicantStaIfaceCallback::onUsdSubscribeConfigFailed,
+			std::placeholders::_1, cmd_id));
+}
+
+UsdServiceProtoType convertUsdServiceProtoTypeToAidl(nan_service_protocol_type type) {
+	switch (type) {
+		case NAN_SRV_PROTO_GENERIC:
+			return UsdServiceProtoType::GENERIC;
+		case NAN_SRV_PROTO_CSA_MATTER:
+			return UsdServiceProtoType::CSA_MATTER;
+		default:
+			// Should not reach here
+			wpa_printf(MSG_ERROR, "Received invalid USD proto type %d from internal",
+				static_cast<int>(type));
+			return UsdServiceProtoType::GENERIC;
+	}
+}
+
+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) {
+	// TODO: Fill the matchFilter field in the AIDL struct
+	UsdServiceDiscoveryInfo discoveryInfo;
+	discoveryInfo.ownId = own_id;
+	discoveryInfo.peerId = peer_id;
+	discoveryInfo.peerMacAddress = macAddrToArray(peer_addr);
+	discoveryInfo.protoType = convertUsdServiceProtoTypeToAidl(srv_proto_type);
+	discoveryInfo.serviceSpecificInfo = byteArrToVec(ssi, ssi_len);
+	discoveryInfo.isFsd = fsd;
+	return discoveryInfo;
+}
+
+void AidlManager::notifyUsdServiceDiscovered(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 || !ssi) return;
+	if (!areAidlServiceAndClientAtLeastVersion(4)) return;
+	UsdServiceDiscoveryInfo discoveryInfo = createUsdServiceDiscoveryInfo(
+		srv_proto_type, subscribe_id, peer_publish_id, peer_addr, fsd, ssi, ssi_len);
+	callWithEachStaIfaceCallback(
+		misc_utils::charBufToString(wpa_s->ifname), std::bind(
+			&ISupplicantStaIfaceCallback::onUsdServiceDiscovered,
+			std::placeholders::_1, discoveryInfo));
+}
+
+void AidlManager::notifyUsdPublishReplied(struct wpa_supplicant *wpa_s,
+		enum nan_service_protocol_type srv_proto_type,
+		int publish_id, int peer_subscribe_id,
+		const u8 *peer_addr, const u8 *ssi, size_t ssi_len)
+{
+	if (!wpa_s || !peer_addr || !ssi) return;
+	if (!areAidlServiceAndClientAtLeastVersion(4)) return;
+	UsdServiceDiscoveryInfo discoveryInfo = createUsdServiceDiscoveryInfo(
+		srv_proto_type, publish_id, peer_subscribe_id, peer_addr, false /* fsd */,
+		ssi, ssi_len);
+	callWithEachStaIfaceCallback(
+		misc_utils::charBufToString(wpa_s->ifname), std::bind(
+			&ISupplicantStaIfaceCallback::onUsdPublishReplied,
+			std::placeholders::_1, discoveryInfo));
+}
+
+void AidlManager::notifyUsdMessageReceived(struct wpa_supplicant *wpa_s, int id,
+		int peer_instance_id, const u8 *peer_addr,
+		const u8 *message, size_t message_len)
+{
+	if (!wpa_s || !peer_addr || !message) return;
+	if (!areAidlServiceAndClientAtLeastVersion(4)) return;
+
+	UsdMessageInfo messageInfo;
+	messageInfo.ownId = id;
+	messageInfo.peerId = peer_instance_id;
+	messageInfo.peerMacAddress = macAddrToArray(peer_addr);
+	messageInfo.message = byteArrToVec(message, message_len);
+
+	callWithEachStaIfaceCallback(
+		misc_utils::charBufToString(wpa_s->ifname), std::bind(
+			&ISupplicantStaIfaceCallback::onUsdMessageReceived,
+			std::placeholders::_1, messageInfo));
+}
+
+UsdTerminateReasonCode convertUsdTerminateReasonCodeToAidl(nan_de_reason reason) {
+	switch (reason) {
+	case NAN_DE_REASON_TIMEOUT:
+		return UsdTerminateReasonCode::TIMEOUT;
+	case NAN_DE_REASON_USER_REQUEST:
+		return UsdTerminateReasonCode::USER_REQUEST;
+	case NAN_DE_REASON_FAILURE:
+		return UsdTerminateReasonCode::FAILURE;
+	default:
+		return UsdTerminateReasonCode::UNKNOWN;
+	}
+}
+
+void AidlManager::notifyUsdPublishTerminated(struct wpa_supplicant *wpa_s,
+		int publish_id, enum nan_de_reason reason)
+{
+	if (!wpa_s) return;
+	if (!areAidlServiceAndClientAtLeastVersion(4)) return;
+	callWithEachStaIfaceCallback(
+		misc_utils::charBufToString(wpa_s->ifname), std::bind(
+			&ISupplicantStaIfaceCallback::onUsdPublishTerminated,
+			std::placeholders::_1, publish_id,
+			convertUsdTerminateReasonCodeToAidl(reason)));
+}
+
+void AidlManager::notifyUsdSubscribeTerminated(struct wpa_supplicant *wpa_s,
+		int subscribe_id, enum nan_de_reason reason)
+{
+	if (!wpa_s) return;
+	if (!areAidlServiceAndClientAtLeastVersion(4)) return;
+	callWithEachStaIfaceCallback(
+		misc_utils::charBufToString(wpa_s->ifname), std::bind(
+			&ISupplicantStaIfaceCallback::onUsdSubscribeTerminated,
+			std::placeholders::_1, subscribe_id,
+			convertUsdTerminateReasonCodeToAidl(reason)));
+}
+
 }  // namespace supplicant
 }  // namespace wifi
 }  // namespace hardware
diff --git a/wpa_supplicant/aidl/vendor/aidl_manager.h b/wpa_supplicant/aidl/vendor/aidl_manager.h
index 46a40aa..d40837c 100644
--- a/wpa_supplicant/aidl/vendor/aidl_manager.h
+++ b/wpa_supplicant/aidl/vendor/aidl_manager.h
@@ -178,6 +178,27 @@
 			unsigned int count, int **scs_resp);
 	void notifyMloLinksInfoChanged(struct wpa_supplicant *wpa_s,
 				       enum mlo_info_change_reason reason);
+	void notifyUsdPublishStarted(struct wpa_supplicant *wpa_s,
+			int cmd_id, int publish_id);
+	void notifyUsdSubscribeStarted(struct wpa_supplicant *wpa_s,
+			int cmd_id, int subscribe_id);
+	void notifyUsdPublishConfigFailed(struct wpa_supplicant *wpa_s, int cmd_id);
+	void notifyUsdSubscribeConfigFailed(struct wpa_supplicant *wpa_s, int cmd_id);
+	void notifyUsdServiceDiscovered(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);
+	void notifyUsdPublishReplied(struct wpa_supplicant *wpa_s,
+			enum nan_service_protocol_type srv_proto_type,
+			int publish_id, int peer_subscribe_id,
+			const u8 *peer_addr, const u8 *ssi, size_t ssi_len);
+	void notifyUsdMessageReceived(struct wpa_supplicant *wpa_s, int id,
+			int peer_instance_id, const u8 *peer_addr,
+			const u8 *message, size_t message_len);
+	void notifyUsdPublishTerminated(struct wpa_supplicant *wpa_s,
+			int publish_id, enum nan_de_reason reason);
+	void notifyUsdSubscribeTerminated(struct wpa_supplicant *wpa_s,
+			int subscribe_id, enum nan_de_reason reason);
 
 	// Methods called from aidl objects.
 	int32_t isAidlServiceVersionAtLeast(int32_t expected_version);
diff --git a/wpa_supplicant/aidl/vendor/sta_iface.cpp b/wpa_supplicant/aidl/vendor/sta_iface.cpp
index f9ed88b..478874d 100644
--- a/wpa_supplicant/aidl/vendor/sta_iface.cpp
+++ b/wpa_supplicant/aidl/vendor/sta_iface.cpp
@@ -38,6 +38,12 @@
 using aidl::android::hardware::wifi::supplicant::LegacyMode;
 using aidl::android::hardware::wifi::supplicant::RxFilterType;
 using aidl::android::hardware::wifi::supplicant::SupplicantStatusCode;
+using aidl::android::hardware::wifi::supplicant::UsdBaseConfig;
+using aidl::android::hardware::wifi::supplicant::UsdCapabilities;
+using aidl::android::hardware::wifi::supplicant::UsdPublishConfig;
+using aidl::android::hardware::wifi::supplicant::UsdPublishTransmissionType;
+using aidl::android::hardware::wifi::supplicant::UsdServiceProtoType;
+using aidl::android::hardware::wifi::supplicant::UsdSubscribeConfig;
 using aidl::android::hardware::wifi::supplicant::WifiChannelWidthInMhz;
 using aidl::android::hardware::wifi::supplicant::WifiTechnology;
 using aidl::android::hardware::wifi::supplicant::misc_utils::createStatus;
@@ -92,6 +98,21 @@
 	WPA_ASSERT(false);
 }
 
+nan_service_protocol_type convertAidlServiceProtoTypeToInternal(
+	UsdServiceProtoType type)
+{
+	switch (type) {
+	case UsdServiceProtoType::GENERIC:
+		return NAN_SRV_PROTO_GENERIC;
+	case UsdServiceProtoType::CSA_MATTER:
+		return NAN_SRV_PROTO_CSA_MATTER;
+	default:
+		// Default case is not expected, due
+		// to the USD validation method
+		return NAN_SRV_PROTO_GENERIC;
+	};
+}
+
 ndk::ScopedAStatus doZeroArgDriverCommand(
 	struct wpa_supplicant *wpa_s, const char *cmd)
 {
@@ -292,6 +313,120 @@
 	return arr;
 }
 
+template <typename T>
+inline bool checkContainerSize(const T& container, int maxSize) {
+  return container.size() <= maxSize;
+}
+
+template <typename T>
+inline bool isValidEnumValue(T value, T enumRangeMin, T enumRangeMax) {
+	return static_cast<uint32_t>(value) >= static_cast<uint32_t>(enumRangeMin)
+		&& static_cast<uint32_t>(value) <= static_cast<uint32_t>(enumRangeMax);
+}
+
+bool validateUsdBaseConfig(UsdBaseConfig baseConfig) {
+	if (!isValidEnumValue(baseConfig.serviceProtoType,
+			UsdServiceProtoType::GENERIC, UsdServiceProtoType::CSA_MATTER)) {
+		wpa_printf(MSG_ERROR, "Unknown protocol type received: %d",
+			static_cast<int>(baseConfig.serviceProtoType));
+		return false;
+	}
+	if (!checkContainerSize(baseConfig.serviceName, kMaxUsdServiceNameLengthBytes)) {
+		wpa_printf(MSG_ERROR, "Service name of size %zu exceeds the supported size of %d",
+			baseConfig.serviceName.size(), kMaxUsdServiceNameLengthBytes);
+		return false;
+	}
+	if (!checkContainerSize(baseConfig.serviceSpecificInfo, kMaxUsdLocalSsiLengthBytes)) {
+		wpa_printf(MSG_ERROR, "Service specific info of size %zu exceeds"
+			" the supported size of %d", baseConfig.serviceSpecificInfo.size(),
+			kMaxUsdLocalSsiLengthBytes);
+		return false;
+	}
+	if (baseConfig.txMatchFilter.has_value() && !checkContainerSize(
+			baseConfig.txMatchFilter.value(), kMaxUsdMatchFilterLengthBytes)) {
+		wpa_printf(MSG_ERROR, "TX match filter of size %zu exceeds"
+			" the supported size of %d", baseConfig.txMatchFilter.value().size(),
+			kMaxUsdMatchFilterLengthBytes);
+		return false;
+	}
+	if (baseConfig.rxMatchFilter.has_value() && !checkContainerSize(
+			baseConfig.rxMatchFilter.value(), kMaxUsdMatchFilterLengthBytes)) {
+		wpa_printf(MSG_ERROR, "RX match filter of size %zu exceeds"
+			" the supported size of %d", baseConfig.rxMatchFilter.value().size(),
+			kMaxUsdMatchFilterLengthBytes);
+		return false;
+	}
+	return true;
+}
+
+bool validateUsdPublishConfig(UsdPublishConfig publishConfig) {
+	if (!validateUsdBaseConfig(publishConfig.usdBaseConfig)) {
+		return false;
+	}
+	if (!isValidEnumValue(publishConfig.publishType,
+			UsdPublishConfig::PublishType::SOLICITED_ONLY,
+			UsdPublishConfig::PublishType::SOLICITED_AND_UNSOLICITED)) {
+		wpa_printf(MSG_ERROR, "Unknown publish type received: %d",
+			static_cast<int>(publishConfig.publishType));
+		return false;
+	}
+	if (!isValidEnumValue(publishConfig.transmissionType,
+			UsdPublishTransmissionType::UNICAST,
+			UsdPublishTransmissionType::MULTICAST)) {
+		wpa_printf(MSG_ERROR, "Unknown transmission type received: %d",
+			static_cast<int>(publishConfig.transmissionType));
+		return false;
+	}
+	return true;
+}
+
+bool validateUsdSubscribeConfig(UsdSubscribeConfig subscribeConfig) {
+	if (!validateUsdBaseConfig(subscribeConfig.usdBaseConfig)) {
+		return false;
+	}
+	if (!isValidEnumValue(subscribeConfig.subscribeType,
+			UsdSubscribeConfig::SubscribeType::PASSIVE_MODE,
+			UsdSubscribeConfig::SubscribeType::ACTIVE_MODE)) {
+		wpa_printf(MSG_ERROR, "Unknown subscribe type received: %d",
+			static_cast<int>(subscribeConfig.subscribeType));
+		return false;
+	}
+	return true;
+}
+
+struct nan_publish_params convertAidlNanPublishParamsToInternal(UsdPublishConfig publishConfig) {
+	// TODO: Fill the disable_events field
+	struct nan_publish_params nanPublishParams;
+	nanPublishParams.unsolicited =
+		publishConfig.publishType == UsdPublishConfig::PublishType::UNSOLICITED_ONLY
+			|| publishConfig.publishType == UsdPublishConfig::PublishType::SOLICITED_AND_UNSOLICITED;
+	nanPublishParams.solicited =
+		publishConfig.publishType == UsdPublishConfig::PublishType::SOLICITED_ONLY
+			|| publishConfig.publishType == UsdPublishConfig::PublishType::SOLICITED_AND_UNSOLICITED;
+	nanPublishParams.solicited_multicast = nanPublishParams.solicited &&
+		publishConfig.transmissionType == UsdPublishTransmissionType::MULTICAST;
+	nanPublishParams.ttl = publishConfig.usdBaseConfig.ttlSec;
+	nanPublishParams.fsd = publishConfig.isFsd;
+	nanPublishParams.freq = publishConfig.usdBaseConfig.defaultFreqMhz;
+	nanPublishParams.announcement_period = publishConfig.announcementPeriodMillis;
+	// Pass the original pointer to the freq list, since the receiver will memcpy the data
+	nanPublishParams.freq_list = publishConfig.usdBaseConfig.freqsMhz.data();
+	return nanPublishParams;
+}
+
+struct nan_subscribe_params convertAidlNanSubscribeParamsToInternal(
+		UsdSubscribeConfig subscribeConfig) {
+	struct nan_subscribe_params nanSubscribeParams;
+	nanSubscribeParams.active =
+		subscribeConfig.subscribeType == UsdSubscribeConfig::SubscribeType::ACTIVE_MODE;
+	nanSubscribeParams.ttl = subscribeConfig.usdBaseConfig.ttlSec;
+	nanSubscribeParams.freq = subscribeConfig.usdBaseConfig.defaultFreqMhz;
+	nanSubscribeParams.query_period = subscribeConfig.queryPeriodMillis;
+	// Pass the original pointer to the freq list, since the receiver will memcpy the data
+	nanSubscribeParams.freq_list = subscribeConfig.usdBaseConfig.freqsMhz.data();
+	return nanSubscribeParams;
+}
+
 }  // namespace
 
 namespace aidl {
@@ -863,7 +998,7 @@
 {
 	return validateAndCall(
 		this, SupplicantStatusCode::FAILURE_UNKNOWN,
-		&StaIface::startUsdPublishInternal, in_usdPublishConfig);
+		&StaIface::startUsdPublishInternal, in_cmdId, in_usdPublishConfig);
 }
 
 ::ndk::ScopedAStatus StaIface::startUsdSubscribe(int32_t in_cmdId,
@@ -871,7 +1006,7 @@
 {
 	return validateAndCall(
 		this, SupplicantStatusCode::FAILURE_UNKNOWN,
-		&StaIface::startUsdSubscribeInternal, in_usdSubscribeConfig);
+		&StaIface::startUsdSubscribeInternal, in_cmdId, in_usdSubscribeConfig);
 }
 
 ::ndk::ScopedAStatus StaIface::updateUsdPublish(int32_t in_publishId,
@@ -2628,13 +2763,145 @@
 	return {capabilities, ndk::ScopedAStatus::ok()};
 }
 
+// TODO (b/384527237): Fix linker error to avoid having a separate default implementation
+#ifdef CONFIG_NAN_USD
+
 ndk::ScopedAStatus StaIface::startUsdPublishInternal(
-		const UsdPublishConfig& usdPublishConfig) {
+		int32_t cmdId, const UsdPublishConfig& usdPublishConfig) {
+	if (!validateUsdPublishConfig(usdPublishConfig)) {
+		return createStatus(SupplicantStatusCode::FAILURE_ARGS_INVALID);
+	}
+	auto ssiBuffer = misc_utils::convertVectorToWpaBuf(
+		usdPublishConfig.usdBaseConfig.serviceSpecificInfo);
+	if (ssiBuffer.get() == nullptr) {
+		wpa_printf(MSG_INFO, "Unable to convert USD publish SSI to buffer");
+		return createStatus(SupplicantStatusCode::FAILURE_UNKNOWN);
+	}
+
+	struct wpa_supplicant *wpa_s = retrieveIfacePtr();
+	struct nan_publish_params nanPublishParams =
+		convertAidlNanPublishParamsToInternal(usdPublishConfig);
+
+	int publishId = wpas_nan_usd_publish(
+		wpa_s, usdPublishConfig.usdBaseConfig.serviceName.c_str(),
+		convertAidlServiceProtoTypeToInternal(
+			usdPublishConfig.usdBaseConfig.serviceProtoType),
+		ssiBuffer.get(), &nanPublishParams, false /* p2p */);
+
+	// Core supplicant does not have an internal callback for USD publish, but some
+	// implementations may decide to offload and return the result in a callback.
+	// In our case (core supplicant), the AIDL callback will be invoked directly here.
+	AidlManager *aidl_manager = AidlManager::getInstance();
+	WPA_ASSERT(aidl_manager);
+	if (publishId < 0) {
+		wpa_printf(MSG_INFO, "Failed to configure USD publish");
+		aidl_manager->notifyUsdPublishConfigFailed(wpa_s, cmdId);
+		return createStatus(SupplicantStatusCode::FAILURE_UNKNOWN);
+	}
+	aidl_manager->notifyUsdPublishStarted(wpa_s, cmdId, publishId);
+	return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus StaIface::startUsdSubscribeInternal(
+		int32_t cmdId, const UsdSubscribeConfig& usdSubscribeConfig) {
+	if (!validateUsdSubscribeConfig(usdSubscribeConfig)) {
+		return createStatus(SupplicantStatusCode::FAILURE_ARGS_INVALID);
+	}
+	auto ssiBuffer = misc_utils::convertVectorToWpaBuf(
+		usdSubscribeConfig.usdBaseConfig.serviceSpecificInfo);
+	if (ssiBuffer.get() == nullptr) {
+		wpa_printf(MSG_INFO, "Unable to convert USD subscribe SSI to buffer");
+		return createStatus(SupplicantStatusCode::FAILURE_UNKNOWN);
+	}
+
+	struct wpa_supplicant *wpa_s = retrieveIfacePtr();
+	struct nan_subscribe_params nanSubscribeParams =
+		convertAidlNanSubscribeParamsToInternal(usdSubscribeConfig);
+
+	int subscribeId = wpas_nan_usd_subscribe(
+		wpa_s, usdSubscribeConfig.usdBaseConfig.serviceName.c_str(),
+		convertAidlServiceProtoTypeToInternal(
+			usdSubscribeConfig.usdBaseConfig.serviceProtoType),
+		ssiBuffer.get(), &nanSubscribeParams, false /* p2p */);
+
+	// See comment in startUsdPublishInternal regarding callbacks
+	AidlManager *aidl_manager = AidlManager::getInstance();
+	WPA_ASSERT(aidl_manager);
+	if (subscribeId < 0) {
+		wpa_printf(MSG_INFO, "Failed to configure USD subscribe");
+		aidl_manager->notifyUsdSubscribeConfigFailed(wpa_s, cmdId);
+		return createStatus(SupplicantStatusCode::FAILURE_UNKNOWN);
+	}
+	aidl_manager->notifyUsdSubscribeStarted(wpa_s, cmdId, subscribeId);
+	return ndk::ScopedAStatus::ok();
+}
+
+::ndk::ScopedAStatus StaIface::updateUsdPublishInternal(int32_t publishId,
+		const std::vector<uint8_t>& serviceSpecificInfo) {
+	if (!checkContainerSize(serviceSpecificInfo, kMaxUsdLocalSsiLengthBytes)) {
+		wpa_printf(MSG_ERROR, "Service specific info of size %zu exceeds the"
+			" supported size of %d", serviceSpecificInfo.size(),
+			kMaxUsdLocalSsiLengthBytes);
+		return createStatus(SupplicantStatusCode::FAILURE_ARGS_INVALID);
+	}
+	auto ssiBuffer = misc_utils::convertVectorToWpaBuf(serviceSpecificInfo);
+	if (ssiBuffer.get() == nullptr) {
+		wpa_printf(MSG_INFO, "Unable to convert USD update SSI to buffer");
+		return createStatus(SupplicantStatusCode::FAILURE_UNKNOWN);
+	}
+	int status = wpas_nan_usd_update_publish(
+		retrieveIfacePtr(), publishId, ssiBuffer.get());
+	if (status < 0) {
+		wpa_printf(MSG_INFO, "Failed to update USD publish");
+		return createStatus(SupplicantStatusCode::FAILURE_UNKNOWN);
+	}
+	return ndk::ScopedAStatus::ok();
+}
+
+::ndk::ScopedAStatus StaIface::cancelUsdPublishInternal(int32_t publishId) {
+	// Status code is returned by the callback
+	wpas_nan_usd_cancel_publish(retrieveIfacePtr(), publishId);
+	return ndk::ScopedAStatus::ok();
+}
+
+::ndk::ScopedAStatus StaIface::cancelUsdSubscribeInternal(int32_t subscribeId) {
+	// Status code is returned by the callback
+	wpas_nan_usd_cancel_subscribe(retrieveIfacePtr(), subscribeId);
+	return ndk::ScopedAStatus::ok();
+}
+
+::ndk::ScopedAStatus StaIface::sendUsdMessageInternal(const UsdMessageInfo& messageInfo) {
+	if (!checkContainerSize(messageInfo.message, kMaxUsdLocalSsiLengthBytes)) {
+		wpa_printf(MSG_ERROR, "Message of size %zu exceeds the supported size of %d",
+			messageInfo.message.size(), kMaxUsdLocalSsiLengthBytes);
+		return createStatus(SupplicantStatusCode::FAILURE_ARGS_INVALID);
+	}
+	auto msgBuffer = misc_utils::convertVectorToWpaBuf(messageInfo.message);
+	if (msgBuffer.get() == nullptr) {
+		wpa_printf(MSG_INFO, "Unable to convert message contents to buffer");
+		return createStatus(SupplicantStatusCode::FAILURE_UNKNOWN);
+	}
+	int handle = messageInfo.ownId;
+	int reqInstanceId = messageInfo.peerId;
+	int status = wpas_nan_usd_transmit(
+		retrieveIfacePtr(), handle, msgBuffer.get(), nullptr /* elems */,
+		messageInfo.peerMacAddress.data(), reqInstanceId);
+	if (status < 0) {
+		wpa_printf(MSG_INFO, "Failed to send USD message");
+		return createStatus(SupplicantStatusCode::FAILURE_UNKNOWN);
+	}
+	return ndk::ScopedAStatus::ok();
+}
+
+#else /* CONFIG_NAN_USD */
+
+ndk::ScopedAStatus StaIface::startUsdPublishInternal(
+		int32_t cmdId, const UsdPublishConfig& usdPublishConfig) {
 	return createStatus(SupplicantStatusCode::FAILURE_UNSUPPORTED);
 }
 
 ndk::ScopedAStatus StaIface::startUsdSubscribeInternal(
-		const UsdSubscribeConfig& usdSubscribeConfig) {
+		int32_t cmdId, const UsdSubscribeConfig& usdSubscribeConfig) {
 	return createStatus(SupplicantStatusCode::FAILURE_UNSUPPORTED);
 }
 
@@ -2655,6 +2922,8 @@
 	return createStatus(SupplicantStatusCode::FAILURE_UNSUPPORTED);
 }
 
+#endif /* CONFIG_NAN_USD */
+
 /**
  * Retrieve the underlying |wpa_supplicant| struct
  * pointer for this iface.
diff --git a/wpa_supplicant/aidl/vendor/sta_iface.h b/wpa_supplicant/aidl/vendor/sta_iface.h
index 6c6cfb9..8703aaf 100644
--- a/wpa_supplicant/aidl/vendor/sta_iface.h
+++ b/wpa_supplicant/aidl/vendor/sta_iface.h
@@ -31,6 +31,7 @@
 #include "wpa_supplicant_i.h"
 #include "config.h"
 #include "driver_i.h"
+#include "nan_usd.h"
 #include "wpa.h"
 }
 
@@ -292,8 +293,10 @@
 	::ndk::ScopedAStatus configureMscsInternal(const MscsParams& params);
 	::ndk::ScopedAStatus disableMscsInternal();
 	std::pair<UsdCapabilities, ndk::ScopedAStatus> getUsdCapabilitiesInternal();
-	::ndk::ScopedAStatus startUsdPublishInternal(const UsdPublishConfig& usdPublishConfig);
-	::ndk::ScopedAStatus startUsdSubscribeInternal(const UsdSubscribeConfig& usdSubscribeConfig);
+	::ndk::ScopedAStatus startUsdPublishInternal(
+		int32_t cmdId, const UsdPublishConfig& usdPublishConfig);
+	::ndk::ScopedAStatus startUsdSubscribeInternal(
+		int32_t cmdId, const UsdSubscribeConfig& usdSubscribeConfig);
 	::ndk::ScopedAStatus updateUsdPublishInternal(int32_t publishId,
 		const std::vector<uint8_t>& serviceSpecificInfo);
 	::ndk::ScopedAStatus cancelUsdPublishInternal(int32_t publishId);
diff --git a/wpa_supplicant/notify.c b/wpa_supplicant/notify.c
index 2dc68b0..0cd7c63 100644
--- a/wpa_supplicant/notify.c
+++ b/wpa_supplicant/notify.c
@@ -1512,6 +1512,9 @@
 		subscribe_id, peer_publish_id, MAC2STR(peer_addr),
 		fsd, fsd_gas, srv_proto_type, ssi_hex);
 	os_free(ssi_hex);
+
+	wpas_aidl_notify_usd_service_discovered(wpa_s, srv_proto_type,
+		subscribe_id, peer_publish_id, peer_addr, fsd, ssi, ssi_len);
 }
 
 
@@ -1534,6 +1537,9 @@
 		publish_id, MAC2STR(peer_addr), peer_subscribe_id,
 		srv_proto_type, ssi_hex);
 	os_free(ssi_hex);
+
+	wpas_aidl_notify_usd_publish_replied(wpa_s, srv_proto_type,
+		publish_id, peer_subscribe_id, peer_addr, ssi, ssi_len);
 }
 
 
@@ -1552,6 +1558,9 @@
 		"id=%d peer_instance_id=%d address=" MACSTR " ssi=%s",
 		id, peer_instance_id, MAC2STR(peer_addr), ssi_hex);
 	os_free(ssi_hex);
+
+	wpas_aidl_notify_usd_message_received(wpa_s, id, peer_instance_id,
+		peer_addr, ssi, ssi_len);
 }
 
 
@@ -1577,6 +1586,7 @@
 	wpa_msg(wpa_s, MSG_INFO, NAN_PUBLISH_TERMINATED
 		"publish_id=%d reason=%s",
 		publish_id, nan_reason_txt(reason));
+	wpas_aidl_notify_usd_publish_terminated(wpa_s, publish_id, reason);
 }
 
 
@@ -1587,6 +1597,7 @@
 	wpa_msg(wpa_s, MSG_INFO, NAN_SUBSCRIBE_TERMINATED
 		"subscribe_id=%d reason=%s",
 		subscribe_id, nan_reason_txt(reason));
+	wpas_aidl_notify_usd_subscribe_terminated(wpa_s, subscribe_id, reason);
 }
 
 #endif /* CONFIG_NAN_USD */