Add callback manager class to manage all callbacks
registered with the mainline supplicant.
This is largely equivalent to the aidl_manager
class in the vendor supplicant.
Bug: 365585450
Test: m
Change-Id: I35dee68e1e65bf827a219719f34c4af89a5d3d46
diff --git a/wpa_supplicant/aidl/mainline/callback_manager.cpp b/wpa_supplicant/aidl/mainline/callback_manager.cpp
new file mode 100644
index 0000000..4922ce1
--- /dev/null
+++ b/wpa_supplicant/aidl/mainline/callback_manager.cpp
@@ -0,0 +1,90 @@
+/*
+ * WPA Supplicant - Manager for callback objects
+ * 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 "callback_manager.h"
+
+extern "C"
+{
+#include "utils/common.h"
+#include "wpa_supplicant_i.h"
+}
+
+// Raw pointer to the global structure maintained by the core
+// Declared here to be accessible to onDeath()
+struct wpa_global* wpa_global_;
+
+void onDeath(void* cookie) {
+ wpa_printf(MSG_ERROR, "Client died. Terminating...");
+ wpa_supplicant_terminate_proc(wpa_global_);
+}
+
+CallbackManager* CallbackManager::instance_ = NULL;
+
+void CallbackManager::initialize(struct wpa_global* wpa_global) {
+ wpa_printf(MSG_INFO, "Initializing the callback manager");
+ wpa_global_ = wpa_global;
+ instance_ = new CallbackManager();
+ instance_->death_notifier_ = AIBinder_DeathRecipient_new(onDeath);
+}
+
+CallbackManager* CallbackManager::getInstance() {
+ return instance_;
+}
+
+bool CallbackManager::registerStaIfaceCallback(std::string ifaceName,
+ const std::shared_ptr<IStaInterfaceCallback>& callback) {
+ std::lock_guard<std::mutex> guard(mutex_);
+ if (!callback) {
+ wpa_printf(MSG_ERROR, "Attempted to register a null callback for STA iface %s",
+ ifaceName.c_str());
+ return false;
+ }
+ if (callbackRegisteredForStaIface(ifaceName)) {
+ wpa_printf(MSG_ERROR, "Callback is already registered for STA iface %s",
+ ifaceName.c_str());
+ return false;
+ }
+ binder_status_t status = AIBinder_linkToDeath(callback->asBinder().get(),
+ death_notifier_, nullptr /* cookie */);
+ if (status != STATUS_OK) {
+ wpa_printf(MSG_ERROR, "Received code %d when linking death recipient"
+ " for callback on STA iface %s", status, ifaceName.c_str());
+ return false;
+ }
+ wpa_printf(MSG_INFO, "Registered callback for STA iface %s", ifaceName.c_str());
+ sta_iface_callbacks_[ifaceName] = callback;
+ return true;
+}
+
+void CallbackManager::unregisterStaIfaceCallback(std::string ifaceName) {
+ std::lock_guard<std::mutex> guard(mutex_);
+ wpa_printf(MSG_INFO, "Unregistering callback for STA iface %s",
+ ifaceName.c_str());
+ if (!callbackRegisteredForStaIface(ifaceName)) {
+ wpa_printf(MSG_INFO, "Callback does not need to be unregistered"
+ " for STA iface %s", ifaceName.c_str());
+ return;
+ }
+ auto callback = sta_iface_callbacks_[ifaceName];
+ binder_status_t status = AIBinder_unlinkToDeath(callback->asBinder().get(),
+ death_notifier_, nullptr /* cookie */);
+ if (status != STATUS_OK) {
+ wpa_printf(MSG_ERROR, "Received code %d when unlinking death recipient"
+ " for callback on STA iface %s", status, ifaceName.c_str());
+ }
+ sta_iface_callbacks_.erase(ifaceName);
+}
+
+std::shared_ptr<IStaInterfaceCallback> CallbackManager::getStaIfaceCallback(
+ std::string ifaceName) {
+ std::lock_guard<std::mutex> guard(mutex_);
+ if (!callbackRegisteredForStaIface(ifaceName)) {
+ return nullptr;
+ }
+ return sta_iface_callbacks_[ifaceName];
+}
diff --git a/wpa_supplicant/aidl/mainline/callback_manager.h b/wpa_supplicant/aidl/mainline/callback_manager.h
new file mode 100644
index 0000000..788c7b3
--- /dev/null
+++ b/wpa_supplicant/aidl/mainline/callback_manager.h
@@ -0,0 +1,52 @@
+/*
+ * WPA Supplicant - Manager for callback objects
+ * 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_MANAGER_H
+#define MAINLINE_SUPPLICANT_CALLBACK_MANAGER_H
+
+#include <map>
+#include <mutex>
+#include <string>
+
+#include <aidl/android/system/wifi/mainline_supplicant/IStaInterfaceCallback.h>
+
+using ::aidl::android::system::wifi::mainline_supplicant::IStaInterfaceCallback;
+
+/**
+ * Class to manage all registered callback objects.
+ *
+ * On startup, a singleton instance should be created using initialize().
+ * Subsequent callers should retrieve the singleton using getInstance().
+ */
+class CallbackManager {
+ public:
+ // Singleton access
+ static void initialize(struct wpa_global* wpa_global);
+ static CallbackManager* getInstance();
+
+ // Member functions
+ bool registerStaIfaceCallback(std::string ifaceName,
+ const std::shared_ptr<IStaInterfaceCallback>& callback);
+ void unregisterStaIfaceCallback(std::string ifaceName);
+ std::shared_ptr<IStaInterfaceCallback> getStaIfaceCallback(std::string ifaceName);
+
+ private:
+ inline bool callbackRegisteredForStaIface(std::string ifaceName) {
+ return sta_iface_callbacks_.find(ifaceName) != sta_iface_callbacks_.end();
+ }
+
+ // Singleton instance of this class
+ static CallbackManager* instance_;
+
+ // Member variables
+ std::mutex mutex_;
+ AIBinder_DeathRecipient* death_notifier_;
+ std::map<std::string, std::shared_ptr<IStaInterfaceCallback>> sta_iface_callbacks_;
+};
+
+#endif // MAINLINE_SUPPLICANT_CALLBACK_MANAGER_H
diff --git a/wpa_supplicant/aidl/mainline/mainline_supplicant.cpp b/wpa_supplicant/aidl/mainline/mainline_supplicant.cpp
index b1a873d..a2dc8b7 100644
--- a/wpa_supplicant/aidl/mainline/mainline_supplicant.cpp
+++ b/wpa_supplicant/aidl/mainline/mainline_supplicant.cpp
@@ -7,6 +7,7 @@
*/
#include "aidl/shared/shared_utils.h"
+#include "callback_manager.h"
#include "mainline_supplicant.h"
#include "utils.h"
@@ -80,8 +81,13 @@
return createStatus(SupplicantStatusCode::FAILURE_UNKNOWN);
}
- wpa_printf(MSG_INFO, "Interface %s was removed successfully", ifaceName.c_str());
+ // Remove interface and callback from the internal maps
+ CallbackManager* callbackManager = CallbackManager::getInstance();
+ WPA_ASSERT(callbackManager);
+ callbackManager->unregisterStaIfaceCallback(ifaceName);
active_sta_ifaces_.erase(ifaceName);
+
+ wpa_printf(MSG_INFO, "Interface %s was removed successfully", ifaceName.c_str());
return ndk::ScopedAStatus::ok();
}
diff --git a/wpa_supplicant/aidl/mainline/service.cpp b/wpa_supplicant/aidl/mainline/service.cpp
index da343ea..002abbb 100644
--- a/wpa_supplicant/aidl/mainline/service.cpp
+++ b/wpa_supplicant/aidl/mainline/service.cpp
@@ -9,6 +9,7 @@
#include <android/binder_manager.h>
#include <android/binder_process.h>
+#include "callback_manager.h"
#include "mainline_supplicant.h"
extern "C"
@@ -80,6 +81,7 @@
}
wpa_printf(MSG_INFO, "AIDL setup is complete");
+ CallbackManager::initialize(global);
return priv;
}
diff --git a/wpa_supplicant/aidl/mainline/sta_iface.cpp b/wpa_supplicant/aidl/mainline/sta_iface.cpp
index 08d2b04..90543e6 100644
--- a/wpa_supplicant/aidl/mainline/sta_iface.cpp
+++ b/wpa_supplicant/aidl/mainline/sta_iface.cpp
@@ -6,6 +6,7 @@
* See README for more details.
*/
+#include "callback_manager.h"
#include "sta_iface.h"
#include "usd_utils.h"
@@ -24,8 +25,14 @@
}
::ndk::ScopedAStatus StaIface::registerCallback(
- const std::shared_ptr<IStaInterfaceCallback>& in_callback) {
- return ndk::ScopedAStatus::ok();
+ const std::shared_ptr<IStaInterfaceCallback>& callback) {
+ CallbackManager* callbackManager = CallbackManager::getInstance();
+ WPA_ASSERT(callbackManager);
+ if (callbackManager->registerStaIfaceCallback(iface_name_, callback)) {
+ return ndk::ScopedAStatus::ok();
+ } else {
+ return createStatus(SupplicantStatusCode::FAILURE_UNKNOWN);
+ }
}
::ndk::ScopedAStatus StaIface::getUsdCapabilities(UsdCapabilities* _aidl_return) {