#include <grpc/support/port_platform.h>
#include "src/core/ext/transport/binder/client/jni_utils.h"
#ifndef GRPC_NO_BINDER
#include <grpc/support/log.h>
#include "src/core/lib/gprpp/crash.h"
#if defined(ANDROID) || defined(__ANDROID__)
namespace grpc_binder {
jclass FindNativeConnectionHelper(JNIEnv* env) {
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;
};
static jclass connection_helper_class = do_find();
if (connection_helper_class != nullptr) {
return connection_helper_class;
}
gpr_log(GPR_ERROR,
"Cannot find binder transport Java helper class. Did you invoke "
"grpc::experimental::InitializeBinderChannelJavaClass correctly "
"beforehand? Did the APK correctly include the connection helper "
"class (i.e depends on build target "
"src/core/ext/transport/binder/java/io/grpc/binder/"
"cpp:connection_helper) ?");
return nullptr;
}
void TryEstablishConnection(JNIEnv* env, jobject application,
absl::string_view pkg, absl::string_view cls,
absl::string_view action_name,
absl::string_view conn_id) {
std::string method = "tryEstablishConnection";
std::string type =
"(Landroid/content/Context;Ljava/lang/String;Ljava/lang/String;Ljava/"
"lang/String;Ljava/lang/String;)V";
jclass cl = FindNativeConnectionHelper(env);
if (cl == nullptr) {
return;
}
jmethodID mid = env->GetStaticMethodID(cl, method.c_str(), type.c_str());
if (mid == nullptr) {
gpr_log(GPR_ERROR, "No method id %s", method.c_str());
}
env->CallStaticVoidMethod(cl, mid, application,
env->NewStringUTF(std::string(pkg).c_str()),
env->NewStringUTF(std::string(cls).c_str()),
env->NewStringUTF(std::string(action_name).c_str()),
env->NewStringUTF(std::string(conn_id).c_str()));
}
void TryEstablishConnectionWithUri(JNIEnv* env, jobject application,
absl::string_view uri,
absl::string_view conn_id) {
std::string method = "tryEstablishConnectionWithUri";
std::string type =
"(Landroid/content/Context;Ljava/lang/String;Ljava/lang/String;)V";
jclass cl = FindNativeConnectionHelper(env);
if (cl == nullptr) {
return;
}
jmethodID mid = env->GetStaticMethodID(cl, method.c_str(), type.c_str());
if (mid == nullptr) {
gpr_log(GPR_ERROR, "No method id %s", method.c_str());
}
env->CallStaticVoidMethod(cl, mid, application,
env->NewStringUTF(std::string(uri).c_str()),
env->NewStringUTF(std::string(conn_id).c_str()));
}
bool IsSignatureMatch(JNIEnv* env, jobject context, int uid1, int uid2) {
const std::string method = "isSignatureMatch";
const std::string type = "(Landroid/content/Context;II)Z";
jclass cl = FindNativeConnectionHelper(env);
if (cl == nullptr) {
return false;
}
jmethodID mid = env->GetStaticMethodID(cl, method.c_str(), type.c_str());
if (mid == nullptr) {
gpr_log(GPR_ERROR, "No method id %s", method.c_str());
}
jboolean result = env->CallStaticBooleanMethod(cl, mid, context, uid1, uid2);
return result == JNI_TRUE;
}
}
#endif
#endif