[BinderTransport] Allow finding Java class using custom class finder (#28348)
In some some situation it is not feasible to invoke
`InitializeBinderChannelJavaClass` in non-native threads.
And the intended way to find Java class is through class loader cached
at program initialization.
This commit adds a new API that accepts a class finder from user and
uses the function to find and cache binder transport Java util class.
diff --git a/include/grpcpp/create_channel_binder.h b/include/grpcpp/create_channel_binder.h
index 6a9f6b4..a8f963d 100644
--- a/include/grpcpp/create_channel_binder.h
+++ b/include/grpcpp/create_channel_binder.h
@@ -78,6 +78,15 @@
/// Returns true when the initialization is successful.
bool InitializeBinderChannelJavaClass(void* jni_env_void);
+/// EXPERIMENTAL Alternative version of `InitializeBinderChannelJavaClass(void*
+/// jni_env_void)`. This version used a user-specified function to find the
+/// required internal Java class. When a class is found, the `class_finder`
+/// function should return a local reference to the class (jclass type). The
+/// returned jclass will then be used to create global reference for gRPC to use
+/// it later. After that, gRPC will DeleteLocalRef the returned local reference.
+bool InitializeBinderChannelJavaClass(
+ void* jni_env_void, std::function<void*(std::string)> class_finder);
+
} // namespace experimental
} // namespace grpc
diff --git a/src/core/ext/transport/binder/client/channel_create.cc b/src/core/ext/transport/binder/client/channel_create.cc
index 0d7fb3c..27b6960 100644
--- a/src/core/ext/transport/binder/client/channel_create.cc
+++ b/src/core/ext/transport/binder/client/channel_create.cc
@@ -50,6 +50,7 @@
#include "src/core/ext/transport/binder/wire_format/binder.h"
#include "src/core/ext/transport/binder/wire_format/binder_android.h"
#include "src/core/lib/channel/channel_args.h"
+#include "src/core/lib/config/core_configuration.h"
#include "src/core/lib/surface/channel.h"
#include "src/core/lib/transport/transport.h"
#include "src/cpp/client/create_channel_internal.h"
@@ -122,6 +123,12 @@
static_cast<JNIEnv*>(jni_env_void)) != nullptr;
}
+bool InitializeBinderChannelJavaClass(
+ void* jni_env_void, std::function<void*(std::string)> class_finder) {
+ return grpc_binder::FindNativeConnectionHelper(
+ static_cast<JNIEnv*>(jni_env_void), class_finder) != nullptr;
+}
+
} // namespace experimental
} // namespace grpc
@@ -162,6 +169,16 @@
return {};
}
+bool InitializeBinderChannelJavaClass(
+ void* jni_env_void, std::function<void*(std::string)> class_finder) {
+ gpr_log(GPR_ERROR,
+ "This APK is compiled with Android API level = %d, which is not "
+ "supported. See port_platform.h for supported versions.",
+ __ANDROID_API__);
+ GPR_ASSERT(0);
+ return {};
+}
+
} // namespace experimental
} // namespace grpc
diff --git a/src/core/ext/transport/binder/client/jni_utils.cc b/src/core/ext/transport/binder/client/jni_utils.cc
index 035e40e..0dde0e1 100644
--- a/src/core/ext/transport/binder/client/jni_utils.cc
+++ b/src/core/ext/transport/binder/client/jni_utils.cc
@@ -25,12 +25,20 @@
namespace grpc_binder {
jclass FindNativeConnectionHelper(JNIEnv* env) {
- auto do_find = [env]() {
- jclass cl = env->FindClass("io/grpc/binder/cpp/NativeConnectionHelper");
+ return FindNativeConnectionHelper(
+ env, [env](std::string cl) { return env->FindClass(cl.c_str()); });
+}
+
+jclass FindNativeConnectionHelper(
+ JNIEnv* env, std::function<void*(std::string)> class_finder) {
+ auto do_find = [env, class_finder]() {
+ jclass cl = static_cast<jclass>(
+ class_finder("io/grpc/binder/cpp/NativeConnectionHelper"));
if (cl == nullptr) {
return cl;
}
jclass global_cl = static_cast<jclass>(env->NewGlobalRef(cl));
+ env->DeleteLocalRef(cl);
GPR_ASSERT(global_cl != nullptr);
return global_cl;
};
diff --git a/src/core/ext/transport/binder/client/jni_utils.h b/src/core/ext/transport/binder/client/jni_utils.h
index 24fd9c0..bd065fb 100644
--- a/src/core/ext/transport/binder/client/jni_utils.h
+++ b/src/core/ext/transport/binder/client/jni_utils.h
@@ -31,6 +31,9 @@
// JNI_OnLoad) so subsequent BinderTransport code can find Java class
jclass FindNativeConnectionHelper(JNIEnv* env);
+jclass FindNativeConnectionHelper(
+ JNIEnv* env, std::function<void*(std::string)> class_finder);
+
// Calls Java method NativeConnectionHelper.tryEstablishConnection
void TryEstablishConnection(JNIEnv* env, jobject application,
absl::string_view pkg, absl::string_view cls,