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();
+}
diff --git a/tests/binder_test.cpp b/tests/binder_test.cpp
index a4ea0fd..1f6e5f7 100644
--- a/tests/binder_test.cpp
+++ b/tests/binder_test.cpp
@@ -43,8 +43,11 @@
#include <android-base/macros.h>
#include <android-base/stringprintf.h>
#include <android-base/strings.h>
+#include <binder/IPCThreadState.h>
#include <bpf/BpfMap.h>
#include <bpf/BpfUtils.h>
+#include <com/android/internal/net/BnOemNetdUnsolicitedEventListener.h>
+#include <com/android/internal/net/IOemNetd.h>
#include <cutils/multiuser.h>
#include <gtest/gtest.h>
#include <logwrap/logwrap.h>
@@ -57,7 +60,6 @@
#include "XfrmController.h"
#include "android/net/INetd.h"
#include "binder/IServiceManager.h"
-#include "com/android/internal/net/IOemNetd.h"
#include "netdutils/Stopwatch.h"
#include "netdutils/Syscalls.h"
#include "tun_interface.h"
@@ -3035,7 +3037,7 @@
EXPECT_TRUE(mNetd->networkDestroy(TEST_NETID1).isOk());
}
-TEST_F(BinderTest, OemNetdIsAlive) {
+TEST_F(BinderTest, OemNetdRelated) {
sp<IBinder> binder;
binder::Status status = mNetd->getOemNetd(&binder);
EXPECT_TRUE(status.isOk()) << status.exceptionMessage();
@@ -3043,9 +3045,47 @@
if (binder != nullptr) {
oemNetd = android::interface_cast<com::android::internal::net::IOemNetd>(binder);
}
+ ASSERT_NE(nullptr, oemNetd.get());
TimedOperation t("OemNetd isAlive RPC");
bool isAlive = false;
oemNetd->isAlive(&isAlive);
ASSERT_TRUE(isAlive);
+
+ class TestOemUnsolListener
+ : public com::android::internal::net::BnOemNetdUnsolicitedEventListener {
+ public:
+ android::binder::Status onRegistered() override {
+ std::lock_guard lock(mCvMutex);
+ mCv.notify_one();
+ return android::binder::Status::ok();
+ }
+ std::condition_variable& getCv() { return mCv; }
+ std::mutex& getCvMutex() { return mCvMutex; }
+
+ private:
+ std::mutex mCvMutex;
+ std::condition_variable mCv;
+ };
+
+ // Start the Binder thread pool.
+ android::ProcessState::self()->startThreadPool();
+
+ android::sp<TestOemUnsolListener> testListener = new TestOemUnsolListener();
+
+ auto& cv = testListener->getCv();
+ auto& cvMutex = testListener->getCvMutex();
+
+ {
+ std::unique_lock lock(cvMutex);
+
+ status = oemNetd->registerOemUnsolicitedEventListener(
+ ::android::interface_cast<
+ com::android::internal::net::IOemNetdUnsolicitedEventListener>(
+ testListener));
+ EXPECT_TRUE(status.isOk()) << status.exceptionMessage();
+
+ // Wait for receiving expected events.
+ EXPECT_EQ(std::cv_status::no_timeout, cv.wait_for(lock, std::chrono::seconds(2)));
+ }
}