Allow registering multiple event listeners from the same process
Rather than store the listener in a map keyed by the pid of thecaller,
we simply store them in a set keyed by the unique address of the binder
interface itself.
Test: system/netd/tests/runtests.sh
Change-Id: I811ff356653334df9fb4afa8501cd9375f1bdd68
diff --git a/server/EventReporter.cpp b/server/EventReporter.cpp
index c9d966a..52dd5c9 100644
--- a/server/EventReporter.cpp
+++ b/server/EventReporter.cpp
@@ -38,36 +38,35 @@
return mNetdEventListener;
}
-std::map<pid_t, const android::sp<INetdUnsolicitedEventListener>>
-EventReporter::getNetdUnsolicitedEventListenerVec() {
+EventReporter::UnsolListeners EventReporter::getNetdUnsolicitedEventListeners() {
std::lock_guard lock(mUnsolicitedMutex);
- return mNetdUnsolicitedEventListenerMap;
+ return mUnsolListeners;
}
void EventReporter::registerUnsolEventListener(
- pid_t pid, const android::sp<INetdUnsolicitedEventListener>& listener) {
+ const android::sp<INetdUnsolicitedEventListener>& listener) {
std::lock_guard lock(mUnsolicitedMutex);
- if (mNetdUnsolicitedEventListenerMap.find(pid) != mNetdUnsolicitedEventListenerMap.end()) {
- return;
- }
- mNetdUnsolicitedEventListenerMap.insert({pid, listener});
+ mUnsolListeners.insert(listener);
// Create the death listener.
class DeathRecipient : public android::IBinder::DeathRecipient {
public:
- DeathRecipient(UnsolListenerMap* map, pid_t pid, std::mutex& unsolMutex)
- : mNetdUnsolicitedEventListenerMap(map), mPid(pid), mMutex(unsolMutex) {}
+ DeathRecipient(UnsolListeners* listeners,
+ android::sp<INetdUnsolicitedEventListener> listener, std::mutex& unsolMutex)
+ : mMutex(unsolMutex), mUnsolListeners(listeners), mListener(std::move(listener)) {}
+ ~DeathRecipient() override = default;
private:
void binderDied(const android::wp<android::IBinder>& /* who */) override {
std::lock_guard lock(mMutex);
- mNetdUnsolicitedEventListenerMap->erase(mPid);
+ mUnsolListeners->erase(mListener);
}
- UnsolListenerMap* mNetdUnsolicitedEventListenerMap;
- pid_t mPid;
+
std::mutex& mMutex;
+ UnsolListeners* mUnsolListeners GUARDED_BY(mMutex);
+ android::sp<INetdUnsolicitedEventListener> mListener;
};
android::sp<android::IBinder::DeathRecipient> deathRecipient =
- new DeathRecipient(&mNetdUnsolicitedEventListenerMap, pid, mUnsolicitedMutex);
+ new DeathRecipient(&mUnsolListeners, listener, mUnsolicitedMutex);
android::IInterface::asBinder(listener)->linkToDeath(deathRecipient);
-}
\ No newline at end of file
+}
diff --git a/server/EventReporter.h b/server/EventReporter.h
index 76a0cee..f471d7f 100644
--- a/server/EventReporter.h
+++ b/server/EventReporter.h
@@ -17,9 +17,8 @@
#ifndef NETD_SERVER_EVENT_REPORTER_H
#define NETD_SERVER_EVENT_REPORTER_H
-#include <atomic>
-#include <map>
#include <mutex>
+#include <set>
#include <android-base/thread_annotations.h>
#include <binder/IServiceManager.h>
@@ -32,27 +31,25 @@
*/
class EventReporter {
public:
+ using UnsolListeners = std::set<const android::sp<android::net::INetdUnsolicitedEventListener>>;
+
// Returns the binder reference to the netd events listener service, attempting to fetch it if
// we do not have it already. This method is threadsafe.
android::sp<android::net::metrics::INetdEventListener> getNetdEventListener();
- using UnsolListenerMap =
- std::map<pid_t, const android::sp<android::net::INetdUnsolicitedEventListener>>;
- UnsolListenerMap getNetdUnsolicitedEventListenerVec() EXCLUDES(mUnsolicitedMutex);
+
+ // Returns a copy of the registered listeners.
+ UnsolListeners getNetdUnsolicitedEventListeners() EXCLUDES(mUnsolicitedMutex);
+
void registerUnsolEventListener(
- pid_t pid, const android::sp<android::net::INetdUnsolicitedEventListener>& listener)
+ const android::sp<android::net::INetdUnsolicitedEventListener>& listener)
EXCLUDES(mUnsolicitedMutex);
private:
- // TODO: consider changing this into an atomic type such as
- // std::atomic<android::net::metrics::INetdEventListener> and deleting the mutex.
- //
- // Alternatively, if this locking causes a performance penalty, have each single-threaded
- // caller (FwmarkServer) keep their own per-thread copy of NetdEventListener
- // and remove mNetdEventListener entirely.
std::mutex mEventMutex;
std::mutex mUnsolicitedMutex;
- android::sp<android::net::metrics::INetdEventListener> mNetdEventListener;
- UnsolListenerMap mNetdUnsolicitedEventListenerMap GUARDED_BY(mUnsolicitedMutex);
+ android::sp<android::net::metrics::INetdEventListener> mNetdEventListener
+ GUARDED_BY(mEventMutex);
+ UnsolListeners mUnsolListeners GUARDED_BY(mUnsolicitedMutex);
};
#endif // NETD_SERVER_EVENT_REPORTER_H
diff --git a/server/NetdNativeService.cpp b/server/NetdNativeService.cpp
index c7ea539..ce2dd23 100644
--- a/server/NetdNativeService.cpp
+++ b/server/NetdNativeService.cpp
@@ -1518,10 +1518,8 @@
binder::Status NetdNativeService::registerUnsolicitedEventListener(
const android::sp<android::net::INetdUnsolicitedEventListener>& listener) {
ENFORCE_PERMISSION(NETWORK_STACK);
- pid_t pid = IPCThreadState::self()->getCallingPid();
- auto entry = gLog.newEntry().prettyFunction(__PRETTY_FUNCTION__).arg(pid);
-
- gCtls->eventReporter.registerUnsolEventListener(pid, listener);
+ auto entry = gLog.newEntry().prettyFunction(__PRETTY_FUNCTION__);
+ gCtls->eventReporter.registerUnsolEventListener(listener);
gLog.log(entry.withAutomaticDuration());
return binder::Status::ok();
}
diff --git a/server/NetlinkHandler.cpp b/server/NetlinkHandler.cpp
index af369e2..6e9a1e0 100644
--- a/server/NetlinkHandler.cpp
+++ b/server/NetlinkHandler.cpp
@@ -52,16 +52,15 @@
res; \
})
-#define LOG_EVENT_FUNC(retry, func, ...) \
- do { \
- const auto listenerMap = gCtls->eventReporter.getNetdUnsolicitedEventListenerVec(); \
- for (auto& listener : listenerMap) { \
- auto entry = \
- gUnsolicitedLog.newEntry().function(#func).args(__VA_ARGS__, listener.first); \
- if (retry(listener.second->func(__VA_ARGS__))) { \
- gUnsolicitedLog.log(entry.withAutomaticDuration()); \
- } \
- } \
+#define LOG_EVENT_FUNC(retry, func, ...) \
+ do { \
+ const auto listeners = gCtls->eventReporter.getNetdUnsolicitedEventListeners(); \
+ for (auto& listener : listeners) { \
+ auto entry = gUnsolicitedLog.newEntry().function(#func).args(__VA_ARGS__); \
+ if (retry(listener->func(__VA_ARGS__))) { \
+ gUnsolicitedLog.log(entry.withAutomaticDuration()); \
+ } \
+ } \
} while (0)
namespace android {