Add helper function for getting endpoint binder in Java (#27598)

Also update the server side URI scheme to use path instead of authority

See gRFC L85-core-binder-transport.md for more details
pull/27651/head
Ming-Chuan 3 years ago committed by GitHub
parent b8e01f73a0
commit f58f903a4f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 4
      examples/android/binder/java/io/grpc/binder/cpp/exampleserver/BUILD
  2. 11
      examples/android/binder/java/io/grpc/binder/cpp/exampleserver/ExportedEndpointService.java
  3. 16
      examples/android/binder/java/io/grpc/binder/cpp/exampleserver/native.cc
  4. 1
      src/core/ext/transport/binder/java/io/grpc/binder/cpp/BUILD
  5. 38
      src/core/ext/transport/binder/java/io/grpc/binder/cpp/GrpcCppServerBuilder.java
  6. 1
      src/core/ext/transport/binder/java/io/grpc/binder/cpp/SyncServiceConnection.java
  7. 50
      src/core/ext/transport/binder/server/binder_server.cc
  8. 11
      test/core/transport/binder/end2end/binder_server_test.cc

@ -53,7 +53,9 @@ android_library(
srcs = ["ExportedEndpointService.java"],
exports_manifest = True,
manifest = "AndroidManifest_endpoint.xml",
deps = [],
deps = [
"@binder_transport_android_helper//io/grpc/binder/cpp:connection_helper",
],
)
android_binary(

@ -1,28 +1,25 @@
package io.grpc.binder.cpp.exampleserver;
import android.app.Service;
import android.os.IBinder;
import android.content.Intent;
import android.os.IBinder;
import io.grpc.binder.cpp.GrpcCppServerBuilder;
/** Exposes gRPC services running in the main process */
public final class ExportedEndpointService extends Service {
private final IBinder binder;
static {
System.loadLibrary("app");
}
public ExportedEndpointService() {
init_grpc_server();
binder = get_endpoint_binder();
}
@Override
public IBinder onBind(Intent intent) {
return binder;
// The argument should match the URI passed into grpc::ServerBuilder::AddListeningPort
return GrpcCppServerBuilder.GetEndpointBinder("binder:example.service");
}
public native void init_grpc_server();
public native IBinder get_endpoint_binder();
}

@ -63,24 +63,10 @@ Java_io_grpc_binder_cpp_exampleserver_ExportedEndpointService_init_1grpc_1server
// TODO(mingcl): Use same signature security after it become available
server_builder.AddListeningPort(
"binder://example.service",
"binder:example.service",
grpc::experimental::BinderServerCredentials(
std::make_shared<
grpc::experimental::binder::UntrustedSecurityPolicy>()));
server = server_builder.BuildAndStart();
}
extern "C" JNIEXPORT jobject JNICALL
Java_io_grpc_binder_cpp_exampleserver_ExportedEndpointService_get_1endpoint_1binder(
JNIEnv* env, jobject /*this*/) {
__android_log_print(ANDROID_LOG_INFO, "DemoServer", "Line number %d",
__LINE__);
auto ai_binder = static_cast<AIBinder*>(
grpc::experimental::binder::GetEndpointBinder("example.service"));
__android_log_print(ANDROID_LOG_INFO, "DemoServer", "ai_binder = %p",
ai_binder);
return AIBinder_toJavaBinder(env, ai_binder);
}

@ -19,6 +19,7 @@ licenses(["notice"])
android_library(
name = "connection_helper",
srcs = [
"GrpcCppServerBuilder.java",
"NativeConnectionHelper.java",
"SyncServiceConnection.java",
],

@ -0,0 +1,38 @@
// Copyright 2021 gRPC authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package io.grpc.binder.cpp;
import android.os.IBinder;
import android.util.Log;
/* EXPERIMENTAL. Provides a interface to get endpoint binder from C++ */
public class GrpcCppServerBuilder {
private static final String logTag = "GrpcCppServerBuilder";
public static IBinder GetEndpointBinder(String uri) {
String scheme = "binder:";
if (uri.startsWith(scheme)) {
String path = uri.substring(scheme.length());
// TODO(mingcl): Consider if we would like to make sure the path only contain valid
// characters here
return GetEndpointBinderInternal(path);
} else {
Log.e(logTag, "URI " + uri + " does not start with 'binder:'");
return null;
}
}
private static native IBinder GetEndpointBinderInternal(String conn_id);
}

@ -35,6 +35,7 @@ public class SyncServiceConnection implements ServiceConnection {
@Override
public void onServiceConnected(ComponentName className, IBinder service) {
Log.e(logTag, "Service has connected: ");
// TODO(mingcl): Check if service is null here
synchronized (this) {
mService = service;
}

@ -30,6 +30,46 @@
#include "src/core/lib/surface/server.h"
#include "src/core/lib/transport/error_utils.h"
#ifdef GPR_SUPPORT_BINDER_TRANSPORT
#include <android/binder_ibinder.h>
#include <android/binder_ibinder_jni.h>
#include <jni.h>
extern "C" {
// This will be invoked from
// src/core/ext/transport/binder/java/io/grpc/binder/cpp/GrpcCppServerBuilder.java
JNIEXPORT jobject JNICALL
Java_io_grpc_binder_cpp_GrpcCppServerBuilder_GetEndpointBinderInternal__Ljava_lang_String_2(
JNIEnv* jni_env, jobject, jstring conn_id_jstring) {
AIBinder* ai_binder = nullptr;
{
// This block is the scope of conn_id c-string
jboolean isCopy;
const char* conn_id = jni_env->GetStringUTFChars(conn_id_jstring, &isCopy);
ai_binder =
static_cast<AIBinder*>(grpc_get_endpoint_binder(std::string(conn_id)));
if (ai_binder == nullptr) {
gpr_log(GPR_ERROR, "Cannot find endpoint binder with connection id = %s",
conn_id);
}
if (isCopy == JNI_TRUE) {
jni_env->ReleaseStringUTFChars(conn_id_jstring, conn_id);
}
}
if (ai_binder == nullptr) {
return nullptr;
}
return AIBinder_toJavaBinder(jni_env, ai_binder);
}
}
#endif
namespace grpc {
namespace experimental {
namespace binder {
@ -190,18 +230,18 @@ bool AddBinderPort(const std::string& addr, grpc_server* server,
BinderTxReceiverFactory factory,
std::shared_ptr<grpc::experimental::binder::SecurityPolicy>
security_policy) {
// TODO(mingcl): Check if the addr is valid here after binder address resolver
// related code are merged.
const std::string kBinderUriScheme = "binder:";
if (addr.compare(0, kBinderUriScheme.size(), kBinderUriScheme) != 0) {
return false;
}
size_t pos = kBinderUriScheme.size();
while (pos < addr.size() && addr[pos] == '/') pos++;
std::string conn_id = addr.substr(kBinderUriScheme.size());
grpc_core::Server* core_server = server->core_server.get();
core_server->AddListener(
grpc_core::OrphanablePtr<grpc_core::Server::ListenerInterface>(
new grpc_core::BinderServerListener(core_server, addr.substr(pos),
std::move(factory),
security_policy)));
new grpc_core::BinderServerListener(
core_server, conn_id, std::move(factory), security_policy)));
return true;
}

@ -108,7 +108,7 @@ TEST(BinderServerCredentialsTest,
grpc::testing::TestServiceImpl service;
server_builder.RegisterService(&service);
server_builder.AddListeningPort(
"binder://fail",
"binder:fail",
grpc::experimental::BinderServerCredentials(
std::make_shared<
grpc::experimental::binder::UntrustedSecurityPolicy>()));
@ -120,7 +120,7 @@ TEST_F(BinderServerTest, BuildAndStart) {
grpc::ServerBuilder server_builder;
grpc::testing::TestServiceImpl service;
server_builder.RegisterService(&service);
server_builder.AddListeningPort("binder://example.service",
server_builder.AddListeningPort("binder:example.service",
grpc::testing::BinderServerCredentials());
std::unique_ptr<grpc::Server> server = server_builder.BuildAndStart();
EXPECT_NE(grpc::experimental::binder::GetEndpointBinder("example.service"),
@ -145,7 +145,7 @@ TEST_F(BinderServerTest, CreateChannelWithEndpointBinder) {
grpc::ServerBuilder server_builder;
grpc::testing::TestServiceImpl service;
server_builder.RegisterService(&service);
server_builder.AddListeningPort("binder://example.service",
server_builder.AddListeningPort("binder:example.service",
grpc::testing::BinderServerCredentials());
std::unique_ptr<grpc::Server> server = server_builder.BuildAndStart();
void* raw_endpoint_binder =
@ -172,9 +172,8 @@ TEST_F(BinderServerTest, CreateChannelWithEndpointBinderMultipleConnections) {
grpc::ServerBuilder server_builder;
grpc::testing::TestServiceImpl service;
server_builder.RegisterService(&service);
server_builder.AddListeningPort(
"binder://example.service.multiple.connections",
grpc::testing::BinderServerCredentials());
server_builder.AddListeningPort("binder:example.service.multiple.connections",
grpc::testing::BinderServerCredentials());
std::unique_ptr<grpc::Server> server = server_builder.BuildAndStart();
void* raw_endpoint_binder = grpc::experimental::binder::GetEndpointBinder(
"example.service.multiple.connections");

Loading…
Cancel
Save