Add template binder call for registering OEM netd unsolicited listener

Bug: 131045919
Test: built, flashed, booted
        system/netd/tests/runtests.sh pass

Change-Id: Id391b3000842ccb4769f0f99bfffcd36a4cdfa35
diff --git a/server/Android.bp b/server/Android.bp
index 7083f47..d1586a2 100644
--- a/server/Android.bp
+++ b/server/Android.bp
@@ -46,10 +46,15 @@
 }
 
 aidl_interface {
+    // This interface is for OEM calls to netd and vice versa that do not exist in AOSP.
+    // Those calls cannot be part of INetd.aidl and INetdUnsolicitedEventListener.aidl
+    // because those interfaces are versioned.
+    // These interfaces must never be versioned or OEMs will not be able to change them.
     name: "oemnetd_aidl_interface",
     local_include_dir: "binder",
     srcs: [
         "binder/com/android/internal/net/IOemNetd.aidl",
+        "binder/com/android/internal/net/IOemNetdUnsolicitedEventListener.aidl",
     ],
 }
 
diff --git a/server/OemNetdListener.cpp b/server/OemNetdListener.cpp
index dddfef0..fb07a80 100644
--- a/server/OemNetdListener.cpp
+++ b/server/OemNetdListener.cpp
@@ -16,15 +16,8 @@
 
 #define LOG_TAG "OemNetd"
 
-#include <log/log.h>
-#include <utils/Errors.h>
-
-#include <binder/IPCThreadState.h>
-
 #include "OemNetdListener.h"
 
-#include "com/android/internal/net/BnOemNetd.h"
-
 namespace com {
 namespace android {
 namespace internal {
@@ -48,6 +41,46 @@
     return ::android::binder::Status::ok();
 }
 
+::android::binder::Status OemNetdListener::registerOemUnsolicitedEventListener(
+        const ::android::sp<IOemNetdUnsolicitedEventListener>& listener) {
+    registerOemUnsolicitedEventListenerInternal(listener);
+    listener->onRegistered();
+    return ::android::binder::Status::ok();
+}
+
+void OemNetdListener::registerOemUnsolicitedEventListenerInternal(
+        const ::android::sp<IOemNetdUnsolicitedEventListener>& listener) {
+    std::lock_guard lock(mOemUnsolicitedMutex);
+
+    // Create the death listener.
+    class DeathRecipient : public ::android::IBinder::DeathRecipient {
+      public:
+        DeathRecipient(OemNetdListener* oemNetdListener,
+                       ::android::sp<IOemNetdUnsolicitedEventListener> listener)
+            : mOemNetdListener(oemNetdListener), mListener(std::move(listener)) {}
+        ~DeathRecipient() override = default;
+        void binderDied(const ::android::wp<::android::IBinder>& /* who */) override {
+            mOemNetdListener->unregisterOemUnsolicitedEventListenerInternal(mListener);
+        }
+
+      private:
+        OemNetdListener* mOemNetdListener;
+        ::android::sp<IOemNetdUnsolicitedEventListener> mListener;
+    };
+    ::android::sp<::android::IBinder::DeathRecipient> deathRecipient =
+            new DeathRecipient(this, listener);
+
+    ::android::IInterface::asBinder(listener)->linkToDeath(deathRecipient);
+
+    mOemUnsolListenerMap.insert({listener, deathRecipient});
+}
+
+void OemNetdListener::unregisterOemUnsolicitedEventListenerInternal(
+        const ::android::sp<IOemNetdUnsolicitedEventListener>& listener) {
+    std::lock_guard lock(mOemUnsolicitedMutex);
+    mOemUnsolListenerMap.erase(listener);
+}
+
 }  // namespace net
 }  // namespace internal
 }  // namespace android
diff --git a/server/OemNetdListener.h b/server/OemNetdListener.h
index a17039c..4fb4fb7 100644
--- a/server/OemNetdListener.h
+++ b/server/OemNetdListener.h
@@ -17,7 +17,12 @@
 #ifndef NETD_SERVER_OEM_NETD_LISTENER_H
 #define NETD_SERVER_OEM_NETD_LISTENER_H
 
+#include <map>
+#include <mutex>
+
+#include <android-base/thread_annotations.h>
 #include "com/android/internal/net/BnOemNetd.h"
+#include "com/android/internal/net/IOemNetdUnsolicitedEventListener.h"
 
 namespace com {
 namespace android {
@@ -26,17 +31,32 @@
 
 class OemNetdListener : public BnOemNetd {
   public:
+    using OemUnsolListenerMap = std::map<const ::android::sp<IOemNetdUnsolicitedEventListener>,
+                                         const ::android::sp<::android::IBinder::DeathRecipient>>;
+
     OemNetdListener() = default;
     ~OemNetdListener() = default;
     static ::android::sp<::android::IBinder> getListener();
 
     ::android::binder::Status isAlive(bool* alive) override;
+    ::android::binder::Status registerOemUnsolicitedEventListener(
+            const ::android::sp<IOemNetdUnsolicitedEventListener>& listener) override;
 
   private:
     std::mutex mMutex;
+    std::mutex mOemUnsolicitedMutex;
+
     ::android::sp<::android::IBinder> mIBinder GUARDED_BY(mMutex);
+    OemUnsolListenerMap mOemUnsolListenerMap GUARDED_BY(mOemUnsolicitedMutex);
 
     ::android::sp<::android::IBinder> getIBinder() EXCLUDES(mMutex);
+
+    void registerOemUnsolicitedEventListenerInternal(
+            const ::android::sp<IOemNetdUnsolicitedEventListener>& listener)
+            EXCLUDES(mOemUnsolicitedMutex);
+    void unregisterOemUnsolicitedEventListenerInternal(
+            const ::android::sp<IOemNetdUnsolicitedEventListener>& listener)
+            EXCLUDES(mOemUnsolicitedMutex);
 };
 
 }  // namespace net
diff --git a/server/binder/com/android/internal/net/IOemNetd.aidl b/server/binder/com/android/internal/net/IOemNetd.aidl
index 7b22389..bd55106 100644
--- a/server/binder/com/android/internal/net/IOemNetd.aidl
+++ b/server/binder/com/android/internal/net/IOemNetd.aidl
@@ -16,10 +16,19 @@
 
 package com.android.internal.net;
 
+import com.android.internal.net.IOemNetdUnsolicitedEventListener;
+
 /** {@hide} */
 interface IOemNetd {
-    /**
-     * Returns true if the service is responding.
-     */
+   /**
+    * Returns true if the service is responding.
+    */
     boolean isAlive();
+
+   /**
+    * Register oem unsolicited event listener
+    *
+    * @param listener oem unsolicited event listener to register
+    */
+    void registerOemUnsolicitedEventListener(IOemNetdUnsolicitedEventListener listener);
 }
diff --git a/server/binder/com/android/internal/net/IOemNetdUnsolicitedEventListener.aidl b/server/binder/com/android/internal/net/IOemNetdUnsolicitedEventListener.aidl
new file mode 100644
index 0000000..e2c6882
--- /dev/null
+++ b/server/binder/com/android/internal/net/IOemNetdUnsolicitedEventListener.aidl
@@ -0,0 +1,30 @@
+/**
+ * Copyright (c) 2019, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.net;
+
+/**
+ * {@hide}
+ */
+oneway interface IOemNetdUnsolicitedEventListener {
+
+   /**
+    * Notifies that a listener is registered.
+    *
+    * It is a sample method and used for testing.
+    */
+    void onRegistered();
+}