Merge "Allow AIBinder<->IBinder when sharing libbinder."
diff --git a/libs/binder/ndk/ibinder.cpp b/libs/binder/ndk/ibinder.cpp
index 7540cae..d287290 100644
--- a/libs/binder/ndk/ibinder.cpp
+++ b/libs/binder/ndk/ibinder.cpp
@@ -698,3 +698,14 @@
const char* AIBinder_getCallingSid() {
return ::android::IPCThreadState::self()->getCallingSid();
}
+
+android::sp<android::IBinder> AIBinder_toPlatformBinder(AIBinder* binder) {
+ if (binder == nullptr) return nullptr;
+ return binder->getBinder();
+}
+
+AIBinder* AIBinder_fromPlatformBinder(const android::sp<android::IBinder>& binder) {
+ sp<AIBinder> ndkBinder = ABpBinder::lookupOrCreateFromBinder(binder);
+ AIBinder_incStrong(ndkBinder.get());
+ return ndkBinder.get();
+}
diff --git a/libs/binder/ndk/include_platform/android/binder_ibinder_platform.h b/libs/binder/ndk/include_platform/android/binder_ibinder_platform.h
index 1f5a237..d4feaba 100644
--- a/libs/binder/ndk/include_platform/android/binder_ibinder_platform.h
+++ b/libs/binder/ndk/include_platform/android/binder_ibinder_platform.h
@@ -18,6 +18,10 @@
#include <android/binder_ibinder.h>
+#if !defined(__ANDROID_APEX__) && !defined(__ANDROID_VNDK__)
+#include <binder/IBinder.h>
+#endif
+
__BEGIN_DECLS
/**
@@ -44,3 +48,33 @@
__attribute__((warn_unused_result)) const char* AIBinder_getCallingSid() __INTRODUCED_IN(31);
__END_DECLS
+
+#if !defined(__ANDROID_APEX__) && !defined(__ANDROID_VNDK__)
+
+/**
+ * Get libbinder version of binder from AIBinder.
+ *
+ * WARNING: function calls to a local object on the other side of this function
+ * will parcel. When converting between binders, keep in mind it is not as
+ * efficient as a direct function call.
+ *
+ * \param binder binder with ownership retained by the client
+ * \return platform binder object
+ */
+android::sp<android::IBinder> AIBinder_toPlatformBinder(AIBinder* binder);
+
+/**
+ * Get libbinder_ndk version of binder from platform binder.
+ *
+ * WARNING: function calls to a local object on the other side of this function
+ * will parcel. When converting between binders, keep in mind it is not as
+ * efficient as a direct function call.
+ *
+ * \param binder platform binder which may be from anywhere (doesn't have to be
+ * created with libbinder_ndK)
+ * \return binder with one reference count of ownership given to the client. See
+ * AIBinder_decStrong
+ */
+AIBinder* AIBinder_fromPlatformBinder(const android::sp<android::IBinder>& binder);
+
+#endif
diff --git a/libs/binder/ndk/libbinder_ndk.map.txt b/libs/binder/ndk/libbinder_ndk.map.txt
index d58b75c..9b5fa26 100644
--- a/libs/binder/ndk/libbinder_ndk.map.txt
+++ b/libs/binder/ndk/libbinder_ndk.map.txt
@@ -95,8 +95,6 @@
AServiceManager_addService; # apex llndk
AServiceManager_checkService; # apex llndk
AServiceManager_getService; # apex llndk
- local:
- *;
};
LIBBINDER_NDK30 { # introduced=30
@@ -111,19 +109,21 @@
AIBinder_markVendorStability; # llndk
AIBinder_markVintfStability; # apex llndk
AIBinder_Class_setHandleShellCommand; # apex llndk
- local:
- *;
};
LIBBINDER_NDK31 { # introduced=31
global:
AIBinder_getCallingSid; # apex
AIBinder_setRequestingSid; # apex
- local:
- *;
};
LIBBINDER_NDK_PLATFORM {
global:
AParcel_getAllowFds;
+ extern "C++" {
+ AIBinder_fromPlatformBinder*;
+ AIBinder_toPlatformBinder*;
+ };
+ local:
+ *;
};
diff --git a/libs/binder/ndk/tests/IBinderNdkUnitTest.aidl b/libs/binder/ndk/tests/IBinderNdkUnitTest.aidl
index 4bba9e4..dc77467 100644
--- a/libs/binder/ndk/tests/IBinderNdkUnitTest.aidl
+++ b/libs/binder/ndk/tests/IBinderNdkUnitTest.aidl
@@ -22,6 +22,8 @@
import IEmpty;
interface IBinderNdkUnitTest {
+ int repeatInt(int a);
+
void takeInterface(IEmpty test);
void forceFlushCommands();
diff --git a/libs/binder/ndk/tests/libbinder_ndk_unit_test.cpp b/libs/binder/ndk/tests/libbinder_ndk_unit_test.cpp
index 6869220..e3fdb4b 100644
--- a/libs/binder/ndk/tests/libbinder_ndk_unit_test.cpp
+++ b/libs/binder/ndk/tests/libbinder_ndk_unit_test.cpp
@@ -44,6 +44,10 @@
constexpr char kBinderNdkUnitTestService[] = "BinderNdkUnitTest";
class MyBinderNdkUnitTest : public aidl::BnBinderNdkUnitTest {
+ ndk::ScopedAStatus repeatInt(int32_t in, int32_t* out) {
+ *out = in;
+ return ndk::ScopedAStatus::ok();
+ }
ndk::ScopedAStatus takeInterface(const std::shared_ptr<aidl::IEmpty>& empty) {
(void)empty;
return ndk::ScopedAStatus::ok();
@@ -329,6 +333,30 @@
EXPECT_TRUE(destroyed);
}
+TEST(NdkBinder, ConvertToPlatformBinder) {
+ for (const ndk::SpAIBinder& binder :
+ {// remote
+ ndk::SpAIBinder(AServiceManager_getService(kBinderNdkUnitTestService)),
+ // local
+ ndk::SharedRefBase::make<MyBinderNdkUnitTest>()->asBinder()}) {
+ // convert to platform binder
+ EXPECT_NE(binder.get(), nullptr);
+ sp<IBinder> platformBinder = AIBinder_toPlatformBinder(binder.get());
+ EXPECT_NE(platformBinder.get(), nullptr);
+ auto proxy = interface_cast<IBinderNdkUnitTest>(platformBinder);
+ EXPECT_NE(proxy, nullptr);
+
+ // use platform binder
+ int out;
+ EXPECT_TRUE(proxy->repeatInt(4, &out).isOk());
+ EXPECT_EQ(out, 4);
+
+ // convert back
+ ndk::SpAIBinder backBinder = ndk::SpAIBinder(AIBinder_fromPlatformBinder(platformBinder));
+ EXPECT_EQ(backBinder.get(), binder.get());
+ }
+}
+
class MyResultReceiver : public BnResultReceiver {
public:
Mutex mMutex;