Add a ChannelArguments option for sepcify custom binder intent (#28723)

User can use
`grpc::ChannelArguments::SetString("grpc.binder.custom_android_intent_action_name", "...")`
to set custom binder intent.
pull/28773/head
Ming-Chuan 3 years ago committed by GitHub
parent 361809aabb
commit 08181286e3
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 14
      examples/android/binder/java/io/grpc/binder/cpp/exampleclient/native.cc
  2. 44
      src/core/ext/transport/binder/client/channel_create.cc
  3. 4
      src/core/ext/transport/binder/client/jni_utils.cc
  4. 1
      src/core/ext/transport/binder/client/jni_utils.h
  5. 4
      src/core/ext/transport/binder/java/io/grpc/binder/cpp/GrpcBinderConnection.java
  6. 4
      src/core/ext/transport/binder/java/io/grpc/binder/cpp/NativeConnectionHelper.java

@ -43,12 +43,17 @@ Java_io_grpc_binder_cpp_exampleclient_ButtonPressHandler_native_1entry(
jint result = env->GetJavaVM(&jvm); jint result = env->GetJavaVM(&jvm);
assert(result == 0); assert(result == 0);
} }
channel = grpc::experimental::CreateBinderChannel( grpc::ChannelArguments ch_args;
// This is not required since "grpc.io.action.BIND" is already the default.
ch_args.SetString("grpc.binder.custom_android_intent_action_name",
"grpc.io.action.BIND");
channel = grpc::experimental::CreateCustomBinderChannel(
env, application, "io.grpc.binder.cpp.exampleserver", env, application, "io.grpc.binder.cpp.exampleserver",
"io.grpc.binder.cpp.exampleserver.ExportedEndpointService", "io.grpc.binder.cpp.exampleserver.ExportedEndpointService",
std::make_shared< std::make_shared<
grpc::experimental::binder::SameSignatureSecurityPolicy>( grpc::experimental::binder::SameSignatureSecurityPolicy>(
jvm, application)); jvm, application),
ch_args);
return env->NewStringUTF("Clicked 1 time, channel created"); return env->NewStringUTF("Clicked 1 time, channel created");
} else { } else {
auto stub = helloworld::Greeter::NewStub(channel); auto stub = helloworld::Greeter::NewStub(channel);
@ -60,6 +65,9 @@ Java_io_grpc_binder_cpp_exampleclient_ButtonPressHandler_native_1entry(
if (status.ok()) { if (status.ok()) {
return env->NewStringUTF(response.message().c_str()); return env->NewStringUTF(response.message().c_str());
} }
return env->NewStringUTF("Clicked more than 1 time. Status not ok"); return env->NewStringUTF(
std::string("Clicked more than 1 time. Status not ok " +
std::to_string(status.error_code()))
.c_str());
} }
} }

@ -55,6 +55,16 @@
#include "src/core/lib/transport/transport.h" #include "src/core/lib/transport/transport.h"
#include "src/cpp/client/create_channel_internal.h" #include "src/cpp/client/create_channel_internal.h"
namespace {
// grpc.io.action.BIND is the standard action name for binding to binder
// transport server.
const char* kStandardActionName = "grpc.io.action.BIND";
// grpc::ChannelArguments key for specifying custom action name.
const char* kCustomIntentActionNameArgKey =
"grpc.binder.custom_android_intent_action_name";
} // namespace
namespace grpc { namespace grpc {
namespace experimental { namespace experimental {
@ -79,9 +89,36 @@ std::shared_ptr<grpc::Channel> CreateCustomBinderChannel(
GPR_ASSERT(jni_env_void != nullptr); GPR_ASSERT(jni_env_void != nullptr);
GPR_ASSERT(security_policy != nullptr); GPR_ASSERT(security_policy != nullptr);
// Generate an unique connection ID that identifies this connection (Useful
// for mapping connection between Java and C++ code).
std::string connection_id = grpc_binder::GetConnectionIdGenerator()->Generate( std::string connection_id = grpc_binder::GetConnectionIdGenerator()->Generate(
std::string(package_name), std::string(class_name)); std::string(package_name), std::string(class_name));
grpc_channel_args channel_args_with_custom_action;
args.SetChannelArgs(&channel_args_with_custom_action);
// Check if user set an option to use non-standard action name to bind to
// server. At this moment this option is not intend for general production use
// and is mainly for stress testing purpose.
std::string action_name = kStandardActionName;
const grpc_arg* action_name_arg = grpc_channel_args_find(
&channel_args_with_custom_action, kCustomIntentActionNameArgKey);
if (action_name_arg != nullptr) {
// The option is set. Now check if it is a string.
char* action_name_arg_string = grpc_channel_arg_get_string(action_name_arg);
if (action_name_arg_string != nullptr) {
action_name = action_name_arg_string;
}
}
grpc_channel_args* channel_args;
{
// Passing the key down will cause gRPC internal error for unclear reason.
// Remove it here.
const char* to_remove[] = {kCustomIntentActionNameArgKey};
channel_args = grpc_channel_args_copy_and_remove(
&channel_args_with_custom_action, to_remove, 1);
}
// After invoking this Java method, Java code will put endpoint binder into // After invoking this Java method, Java code will put endpoint binder into
// `EndpointBinderPool` after the connection succeeds // `EndpointBinderPool` after the connection succeeds
// TODO(mingcl): Consider if we want to delay the connection establishment // TODO(mingcl): Consider if we want to delay the connection establishment
@ -89,13 +126,11 @@ std::shared_ptr<grpc::Channel> CreateCustomBinderChannel(
// see any benifits doing that. // see any benifits doing that.
grpc_binder::TryEstablishConnection(static_cast<JNIEnv*>(jni_env_void), grpc_binder::TryEstablishConnection(static_cast<JNIEnv*>(jni_env_void),
application, package_name, class_name, application, package_name, class_name,
connection_id); action_name, connection_id);
// Set server URI to a URI that contains connection id. The URI will be used // Set server URI to a URI that contains connection id. The URI will be used
// by subchannel connector to obtain correct endpoint binder from // by subchannel connector to obtain correct endpoint binder from
// `EndpointBinderPool`. // `EndpointBinderPool`.
grpc_channel_args channel_args;
args.SetChannelArgs(&channel_args);
grpc_channel_args* new_args; grpc_channel_args* new_args;
{ {
grpc_arg server_uri_arg = grpc_channel_arg_string_create( grpc_arg server_uri_arg = grpc_channel_arg_string_create(
@ -103,7 +138,7 @@ std::shared_ptr<grpc::Channel> CreateCustomBinderChannel(
const_cast<char*>(("binder:" + connection_id).c_str())); const_cast<char*>(("binder:" + connection_id).c_str()));
const char* to_remove[] = {GRPC_ARG_SERVER_URI}; const char* to_remove[] = {GRPC_ARG_SERVER_URI};
new_args = grpc_channel_args_copy_and_add_and_remove( new_args = grpc_channel_args_copy_and_add_and_remove(
&channel_args, to_remove, 1, &server_uri_arg, 1); channel_args, to_remove, 1, &server_uri_arg, 1);
} }
grpc_binder::GetSecurityPolicySetting()->Set(connection_id, security_policy); grpc_binder::GetSecurityPolicySetting()->Set(connection_id, security_policy);
@ -114,6 +149,7 @@ std::shared_ptr<grpc::Channel> CreateCustomBinderChannel(
std::unique_ptr<experimental::ClientInterceptorFactoryInterface>>()); std::unique_ptr<experimental::ClientInterceptorFactoryInterface>>());
grpc_channel_args_destroy(new_args); grpc_channel_args_destroy(new_args);
grpc_channel_args_destroy(channel_args);
return channel; return channel;
} }

@ -65,11 +65,12 @@ jclass FindNativeConnectionHelper(
void TryEstablishConnection(JNIEnv* env, jobject application, void TryEstablishConnection(JNIEnv* env, jobject application,
absl::string_view pkg, absl::string_view cls, absl::string_view pkg, absl::string_view cls,
absl::string_view action_name,
absl::string_view conn_id) { absl::string_view conn_id) {
std::string method = "tryEstablishConnection"; std::string method = "tryEstablishConnection";
std::string type = std::string type =
"(Landroid/content/Context;Ljava/lang/String;Ljava/lang/String;Ljava/" "(Landroid/content/Context;Ljava/lang/String;Ljava/lang/String;Ljava/"
"lang/String;)V"; "lang/String;Ljava/lang/String;)V";
jclass cl = FindNativeConnectionHelper(env); jclass cl = FindNativeConnectionHelper(env);
if (cl == nullptr) { if (cl == nullptr) {
@ -84,6 +85,7 @@ void TryEstablishConnection(JNIEnv* env, jobject application,
env->CallStaticVoidMethod(cl, mid, application, env->CallStaticVoidMethod(cl, mid, application,
env->NewStringUTF(std::string(pkg).c_str()), env->NewStringUTF(std::string(pkg).c_str()),
env->NewStringUTF(std::string(cls).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())); env->NewStringUTF(std::string(conn_id).c_str()));
} }

@ -40,6 +40,7 @@ jclass FindNativeConnectionHelper(
// Calls Java method NativeConnectionHelper.tryEstablishConnection // Calls Java method NativeConnectionHelper.tryEstablishConnection
void TryEstablishConnection(JNIEnv* env, jobject application, void TryEstablishConnection(JNIEnv* env, jobject application,
absl::string_view pkg, absl::string_view cls, absl::string_view pkg, absl::string_view cls,
absl::string_view action_name,
absl::string_view conn_id); absl::string_view conn_id);
// Calls Java method NativeConnectionHelper.isSignatureMatch. // Calls Java method NativeConnectionHelper.isSignatureMatch.

@ -60,9 +60,9 @@ public class GrpcBinderConnection implements ServiceConnection {
Log.e(logTag, "Service has disconnected. mConnId = " + mConnId); Log.e(logTag, "Service has disconnected. mConnId = " + mConnId);
} }
public void tryConnect(String pkg, String cls) { public void tryConnect(String pkg, String cls, String action_name) {
synchronized (this) { synchronized (this) {
Intent intent = new Intent("grpc.io.action.BIND"); Intent intent = new Intent(action_name);
ComponentName compName = new ComponentName(pkg, cls); ComponentName compName = new ComponentName(pkg, cls);
intent.setComponent(compName); intent.setComponent(compName);
// Will return true if the system is in the process of bringing up a service that your client // Will return true if the system is in the process of bringing up a service that your client

@ -30,10 +30,10 @@ final class NativeConnectionHelper {
// Maps connection id to GrpcBinderConnection instances // Maps connection id to GrpcBinderConnection instances
static Map<String, GrpcBinderConnection> s = new HashMap<>(); static Map<String, GrpcBinderConnection> s = new HashMap<>();
static void tryEstablishConnection(Context context, String pkg, String cls, String connId) { static void tryEstablishConnection(Context context, String pkg, String cls, String action_name, String connId) {
// TODO(mingcl): Assert that connId is unique // TODO(mingcl): Assert that connId is unique
s.put(connId, new GrpcBinderConnection(context, connId)); s.put(connId, new GrpcBinderConnection(context, connId));
s.get(connId).tryConnect(pkg, cls); s.get(connId).tryConnect(pkg, cls, action_name);
} }
// Returns true if the packages signature of the 2 UIDs match. // Returns true if the packages signature of the 2 UIDs match.

Loading…
Cancel
Save