libbinder_ndk: Expose UTF-8 interface descriptor string
We want to be able to expose the original char* interface descriptor
string from AIBinder_Class to NDK clients. Rather than converting the
String16 representation, which presents difficulties regarding
allocation cleanup, we just store an extra copy of the string for now.
Eventually, we would like to transition interface descriptors to UTF-8
and avoid String16 entirely, so this change is a partial step in that
direction and avoids exposing a UTF-16 string through the NDK API.
Bug: 167723746
Test: atest libbinder_ndk_unit_test CtsBinderNdkTestCases
Change-Id: I79d11f26245e229acde753f8c76c53cd0970c8ed
diff --git a/libs/binder/ndk/ibinder.cpp b/libs/binder/ndk/ibinder.cpp
index 5e2e1bd..350c658 100644
--- a/libs/binder/ndk/ibinder.cpp
+++ b/libs/binder/ndk/ibinder.cpp
@@ -307,7 +307,8 @@
: onCreate(onCreate),
onDestroy(onDestroy),
onTransact(onTransact),
- mInterfaceDescriptor(interfaceDescriptor) {}
+ mInterfaceDescriptor(interfaceDescriptor),
+ mWideInterfaceDescriptor(interfaceDescriptor) {}
AIBinder_Class* AIBinder_Class_define(const char* interfaceDescriptor,
AIBinder_Class_onCreate onCreate,
@@ -335,6 +336,12 @@
clazz->handleShellCommand = handleShellCommand;
}
+const char* AIBinder_Class_getDescriptor(const AIBinder_Class* clazz) {
+ CHECK(clazz != nullptr) << "getDescriptor requires non-null clazz";
+
+ return clazz->getInterfaceDescriptorUtf8();
+}
+
void AIBinder_DeathRecipient::TransferDeathRecipient::binderDied(const wp<IBinder>& who) {
CHECK(who == mWho);
diff --git a/libs/binder/ndk/ibinder_internal.h b/libs/binder/ndk/ibinder_internal.h
index 6236e81..6824306 100644
--- a/libs/binder/ndk/ibinder_internal.h
+++ b/libs/binder/ndk/ibinder_internal.h
@@ -112,7 +112,8 @@
AIBinder_Class(const char* interfaceDescriptor, AIBinder_Class_onCreate onCreate,
AIBinder_Class_onDestroy onDestroy, AIBinder_Class_onTransact onTransact);
- const ::android::String16& getInterfaceDescriptor() const { return mInterfaceDescriptor; }
+ const ::android::String16& getInterfaceDescriptor() const { return mWideInterfaceDescriptor; }
+ const char* getInterfaceDescriptorUtf8() const { return mInterfaceDescriptor.c_str(); }
// required to be non-null, implemented for every class
const AIBinder_Class_onCreate onCreate = nullptr;
@@ -124,9 +125,11 @@
AIBinder_handleShellCommand handleShellCommand = nullptr;
private:
+ // Copy of the raw char string for when we don't have to return UTF-16
+ const std::string mInterfaceDescriptor;
// This must be a String16 since BBinder virtual getInterfaceDescriptor returns a reference to
// one.
- const ::android::String16 mInterfaceDescriptor;
+ const ::android::String16 mWideInterfaceDescriptor;
};
// Ownership is like this (when linked to death):
diff --git a/libs/binder/ndk/include_ndk/android/binder_ibinder.h b/libs/binder/ndk/include_ndk/android/binder_ibinder.h
index ce3d1db..5e1ed46 100644
--- a/libs/binder/ndk/include_ndk/android/binder_ibinder.h
+++ b/libs/binder/ndk/include_ndk/android/binder_ibinder.h
@@ -642,6 +642,23 @@
#endif //__ANDROID_API__ >= 30
+#if __ANDROID_API__ >= 31
+
+/**
+ * Retrieve the class descriptor for the class.
+ *
+ * Available since API level 31.
+ *
+ * \param clazz the class to fetch the descriptor from
+ *
+ * \return the class descriptor string. This pointer will never be null; a
+ * descriptor is required to define a class. The pointer is owned by the class
+ * and will remain valid as long as the class does.
+ */
+const char* AIBinder_Class_getDescriptor(const AIBinder_Class* clazz) __INTRODUCED_IN(31);
+
+#endif //__ANDROID_API__ >= 31
+
__END_DECLS
/** @} */
diff --git a/libs/binder/ndk/libbinder_ndk.map.txt b/libs/binder/ndk/libbinder_ndk.map.txt
index 6962f86..e233ffd 100644
--- a/libs/binder/ndk/libbinder_ndk.map.txt
+++ b/libs/binder/ndk/libbinder_ndk.map.txt
@@ -121,6 +121,7 @@
AServiceManager_registerLazyService; # llndk
AServiceManager_waitForService; # apex llndk
+ AIBinder_Class_getDescriptor;
AParcel_appendFrom;
AParcel_create;
AParcel_getDataSize;
diff --git a/libs/binder/ndk/tests/iface.cpp b/libs/binder/ndk/tests/iface.cpp
index a588985..2afe5d2 100644
--- a/libs/binder/ndk/tests/iface.cpp
+++ b/libs/binder/ndk/tests/iface.cpp
@@ -25,7 +25,7 @@
const char* IFoo::kSomeInstanceName = "libbinder_ndk-test-IFoo";
const char* IFoo::kInstanceNameToDieFor = "libbinder_ndk-test-IFoo-to-die";
-const char* kIFooDescriptor = "my-special-IFoo-class";
+const char* IFoo::kIFooDescriptor = "my-special-IFoo-class";
struct IFoo_Class_Data {
sp<IFoo> foo;
diff --git a/libs/binder/ndk/tests/include/iface/iface.h b/libs/binder/ndk/tests/include/iface/iface.h
index d9dd64b..7408d0c 100644
--- a/libs/binder/ndk/tests/include/iface/iface.h
+++ b/libs/binder/ndk/tests/include/iface/iface.h
@@ -27,6 +27,7 @@
public:
static const char* kSomeInstanceName;
static const char* kInstanceNameToDieFor;
+ static const char* kIFooDescriptor;
static AIBinder_Class* kClass;
diff --git a/libs/binder/ndk/tests/libbinder_ndk_unit_test.cpp b/libs/binder/ndk/tests/libbinder_ndk_unit_test.cpp
index f84d9d3..b7df115 100644
--- a/libs/binder/ndk/tests/libbinder_ndk_unit_test.cpp
+++ b/libs/binder/ndk/tests/libbinder_ndk_unit_test.cpp
@@ -39,6 +39,7 @@
#include <condition_variable>
#include <iostream>
#include <mutex>
+#include "android/binder_ibinder.h"
using namespace android;
@@ -543,6 +544,10 @@
EXPECT_EQ("CMD", shellCmdToString(testService, {"C", "M", "D"}));
}
+TEST(NdkBinder, GetClassInterfaceDescriptor) {
+ ASSERT_STREQ(IFoo::kIFooDescriptor, AIBinder_Class_getDescriptor(IFoo::kClass));
+}
+
int main(int argc, char* argv[]) {
::testing::InitGoogleTest(&argc, argv);