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 {