diff --git a/examples/android/binder/java/io/grpc/binder/cpp/exampleclient/native.cc b/examples/android/binder/java/io/grpc/binder/cpp/exampleclient/native.cc index 8f79e940da7..fe7d910f1b4 100644 --- a/examples/android/binder/java/io/grpc/binder/cpp/exampleclient/native.cc +++ b/examples/android/binder/java/io/grpc/binder/cpp/exampleclient/native.cc @@ -43,12 +43,17 @@ Java_io_grpc_binder_cpp_exampleclient_ButtonPressHandler_native_1entry( jint result = env->GetJavaVM(&jvm); 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", "io.grpc.binder.cpp.exampleserver.ExportedEndpointService", std::make_shared< grpc::experimental::binder::SameSignatureSecurityPolicy>( - jvm, application)); + jvm, application), + ch_args); return env->NewStringUTF("Clicked 1 time, channel created"); } else { auto stub = helloworld::Greeter::NewStub(channel); @@ -60,6 +65,9 @@ Java_io_grpc_binder_cpp_exampleclient_ButtonPressHandler_native_1entry( if (status.ok()) { 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()); } } diff --git a/src/core/ext/transport/binder/client/channel_create.cc b/src/core/ext/transport/binder/client/channel_create.cc index 27b69604309..4e4f53cb186 100644 --- a/src/core/ext/transport/binder/client/channel_create.cc +++ b/src/core/ext/transport/binder/client/channel_create.cc @@ -55,6 +55,16 @@ #include "src/core/lib/transport/transport.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 experimental { @@ -79,9 +89,36 @@ std::shared_ptr CreateCustomBinderChannel( GPR_ASSERT(jni_env_void != 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(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 // `EndpointBinderPool` after the connection succeeds // TODO(mingcl): Consider if we want to delay the connection establishment @@ -89,13 +126,11 @@ std::shared_ptr CreateCustomBinderChannel( // see any benifits doing that. grpc_binder::TryEstablishConnection(static_cast(jni_env_void), 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 // by subchannel connector to obtain correct endpoint binder from // `EndpointBinderPool`. - grpc_channel_args channel_args; - args.SetChannelArgs(&channel_args); grpc_channel_args* new_args; { grpc_arg server_uri_arg = grpc_channel_arg_string_create( @@ -103,7 +138,7 @@ std::shared_ptr CreateCustomBinderChannel( const_cast(("binder:" + connection_id).c_str())); const char* to_remove[] = {GRPC_ARG_SERVER_URI}; 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); @@ -114,6 +149,7 @@ std::shared_ptr CreateCustomBinderChannel( std::unique_ptr>()); grpc_channel_args_destroy(new_args); + grpc_channel_args_destroy(channel_args); return channel; } diff --git a/src/core/ext/transport/binder/client/jni_utils.cc b/src/core/ext/transport/binder/client/jni_utils.cc index 867950c7785..1bf1ccdd647 100644 --- a/src/core/ext/transport/binder/client/jni_utils.cc +++ b/src/core/ext/transport/binder/client/jni_utils.cc @@ -65,11 +65,12 @@ jclass FindNativeConnectionHelper( 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;)V"; + "lang/String;Ljava/lang/String;)V"; jclass cl = FindNativeConnectionHelper(env); if (cl == nullptr) { @@ -84,6 +85,7 @@ void TryEstablishConnection(JNIEnv* env, jobject application, 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())); } diff --git a/src/core/ext/transport/binder/client/jni_utils.h b/src/core/ext/transport/binder/client/jni_utils.h index c93feec6691..a50c94bc8c3 100644 --- a/src/core/ext/transport/binder/client/jni_utils.h +++ b/src/core/ext/transport/binder/client/jni_utils.h @@ -40,6 +40,7 @@ jclass FindNativeConnectionHelper( // Calls Java method NativeConnectionHelper.tryEstablishConnection void TryEstablishConnection(JNIEnv* env, jobject application, absl::string_view pkg, absl::string_view cls, + absl::string_view action_name, absl::string_view conn_id); // Calls Java method NativeConnectionHelper.isSignatureMatch. diff --git a/src/core/ext/transport/binder/java/io/grpc/binder/cpp/GrpcBinderConnection.java b/src/core/ext/transport/binder/java/io/grpc/binder/cpp/GrpcBinderConnection.java index 4953113f01d..35f3d84f457 100644 --- a/src/core/ext/transport/binder/java/io/grpc/binder/cpp/GrpcBinderConnection.java +++ b/src/core/ext/transport/binder/java/io/grpc/binder/cpp/GrpcBinderConnection.java @@ -60,9 +60,9 @@ public class GrpcBinderConnection implements ServiceConnection { 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) { - Intent intent = new Intent("grpc.io.action.BIND"); + Intent intent = new Intent(action_name); ComponentName compName = new ComponentName(pkg, cls); intent.setComponent(compName); // Will return true if the system is in the process of bringing up a service that your client diff --git a/src/core/ext/transport/binder/java/io/grpc/binder/cpp/NativeConnectionHelper.java b/src/core/ext/transport/binder/java/io/grpc/binder/cpp/NativeConnectionHelper.java index 79b6d5a07f0..257f65149a7 100644 --- a/src/core/ext/transport/binder/java/io/grpc/binder/cpp/NativeConnectionHelper.java +++ b/src/core/ext/transport/binder/java/io/grpc/binder/cpp/NativeConnectionHelper.java @@ -30,10 +30,10 @@ final class NativeConnectionHelper { // Maps connection id to GrpcBinderConnection instances static Map 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 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.