mirror of https://github.com/grpc/grpc.git
commit
ca58824fdd
3643 changed files with 39455 additions and 39494 deletions
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,93 @@ |
||||
# Copyright 2024 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. |
||||
|
||||
import os |
||||
import re |
||||
import subprocess |
||||
import sys |
||||
import tempfile |
||||
|
||||
_OK_TEST_REGEX = r"^-+.*Ran ([\d]+) tests* in ([\d.]+)s.*OK(?: \(skipped=(\d+)\))?\n$" |
||||
|
||||
# Tests with known exception logs. |
||||
# TODO(sourabhsinghs): Investigate and enable _rpc_part_1_test and _rpc_part_2_test tests. |
||||
_SKIP_TESTS = [ |
||||
"_rpc_part_1_test", |
||||
"_server_shutdown_test", |
||||
"_xds_credentials_test", |
||||
"_server_test", |
||||
"_invalid_metadata_test", |
||||
"_reconnect_test", |
||||
"_channel_close_test", |
||||
"_rpc_part_2_test", |
||||
"_invocation_defects_test", |
||||
"_dynamic_stubs_test", |
||||
"_channel_connectivity_test", |
||||
] |
||||
|
||||
if __name__ == "__main__": |
||||
if len(sys.argv) != 3: |
||||
print(f"USAGE: {sys.argv[0]} TARGET_MODULE", file=sys.stderr) |
||||
sys.exit(1) |
||||
|
||||
test_script = sys.argv[1] |
||||
target_module = sys.argv[2] |
||||
|
||||
if target_module in _SKIP_TESTS: |
||||
print(f"Skipping {target_module}") |
||||
sys.exit(0) |
||||
|
||||
command = [ |
||||
sys.executable, |
||||
os.path.realpath(test_script), |
||||
target_module, |
||||
os.path.dirname(os.path.relpath(__file__)), |
||||
] |
||||
|
||||
with tempfile.TemporaryFile(mode="w+") as stdout_file: |
||||
with tempfile.TemporaryFile(mode="w+") as stderr_file: |
||||
result = subprocess.run( |
||||
command, |
||||
stdout=stdout_file, |
||||
stderr=stderr_file, |
||||
text=True, |
||||
check=True, |
||||
) |
||||
|
||||
stdout_file.seek(0) |
||||
stderr_file.seek(0) |
||||
|
||||
stdout_count = len(stdout_file.readlines()) |
||||
stderr_count = len(stderr_file.readlines()) |
||||
|
||||
if result.returncode != 0: |
||||
sys.exit("Test failure") |
||||
|
||||
stderr_file.seek(0) |
||||
if not re.fullmatch(_OK_TEST_REGEX, stderr_file.read(), re.DOTALL): |
||||
print( |
||||
f"Warning: Excessive error output detected ({stderr_count} lines):" |
||||
) |
||||
stderr_file.seek(0) |
||||
for line in stderr_file: |
||||
print(line) |
||||
|
||||
if stdout_count > 0: |
||||
print( |
||||
f"Warning: Unexpected output detected ({stdout_count} lines):" |
||||
) |
||||
stdout_file.seek(0) |
||||
for line in stdout_file: |
||||
print(line) |
||||
|
@ -0,0 +1,54 @@ |
||||
# Copyright 2024 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. |
||||
|
||||
from typing import Sequence, Optional |
||||
|
||||
import unittest |
||||
import sys |
||||
import pkgutil |
||||
|
||||
|
||||
class SingleLoader(object): |
||||
def __init__(self, pattern: str, unittest_path: str): |
||||
loader = unittest.TestLoader() |
||||
self.suite = unittest.TestSuite() |
||||
tests = [] |
||||
|
||||
for importer, module_name, is_package in pkgutil.walk_packages([unittest_path]): |
||||
if pattern in module_name: |
||||
module = importer.find_module(module_name).load_module(module_name) |
||||
tests.append(loader.loadTestsFromModule(module)) |
||||
if len(tests) != 1: |
||||
raise AssertionError("Expected only 1 test module. Found {}".format(tests)) |
||||
self.suite.addTest(tests[0]) |
||||
|
||||
def loadTestsFromNames(self, names: Sequence[str], module: Optional[str] = None) -> unittest.TestSuite: |
||||
return self.suite |
||||
|
||||
if __name__ == "__main__": |
||||
|
||||
if len(sys.argv) != 3: |
||||
print(f"USAGE: {sys.argv[0]} TARGET_MODULE", file=sys.stderr) |
||||
sys.exit(1) |
||||
|
||||
|
||||
target_module = sys.argv[1] |
||||
unittest_path = sys.argv[2] |
||||
|
||||
loader = SingleLoader(target_module, unittest_path) |
||||
runner = unittest.TextTestRunner(verbosity=0) |
||||
result = runner.run(loader.suite) |
||||
|
||||
if not result.wasSuccessful(): |
||||
sys.exit("Test failure.") |
@ -0,0 +1,73 @@ |
||||
# Copyright 2024 The 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. |
||||
""" |
||||
Houses py_grpc_logging_threshold_test. |
||||
""" |
||||
|
||||
_COPIED_MAIN_SUFFIX = ".logging_threshold.main" |
||||
|
||||
def py_grpc_logging_threshold_test( |
||||
name, |
||||
srcs, |
||||
main = None, |
||||
deps = None, |
||||
data = None, |
||||
**kwargs): |
||||
"""Runs a Python unit test and checks amount of logging against a threshold. |
||||
|
||||
Args: |
||||
name: The name of the test. |
||||
srcs: The source files. |
||||
main: The main file of the test. |
||||
deps: The dependencies of the test. |
||||
data: The data dependencies of the test. |
||||
**kwargs: Any other test arguments. |
||||
""" |
||||
if main == None: |
||||
if len(srcs) != 1: |
||||
fail("When main is not provided, srcs must be of size 1.") |
||||
main = srcs[0] |
||||
deps = [] if deps == None else deps |
||||
data = [] if data == None else data |
||||
|
||||
lib_name = name + ".logging_threshold.lib" |
||||
native.py_library( |
||||
name = lib_name, |
||||
srcs = srcs, |
||||
) |
||||
augmented_deps = deps + [ |
||||
":{}".format(lib_name), |
||||
] |
||||
|
||||
# The main file needs to be in the same package as the test file. |
||||
copied_main_name = name + _COPIED_MAIN_SUFFIX |
||||
copied_main_filename = copied_main_name + ".py" |
||||
native.genrule( |
||||
name = copied_main_name, |
||||
srcs = ["//bazel:_logging_threshold_test_main.py"], |
||||
outs = [copied_main_filename], |
||||
cmd = "cp $< $@", |
||||
) |
||||
|
||||
native.py_test( |
||||
name = name + ".logging_threshold", |
||||
args = ["$(location //bazel:_single_module_tester)", name], |
||||
data = data + ["//bazel:_single_module_tester"], |
||||
deps = augmented_deps, |
||||
srcs = [copied_main_filename], |
||||
main = copied_main_filename, |
||||
python_version = "PY3", |
||||
flaky = False, |
||||
**kwargs |
||||
) |
@ -0,0 +1,19 @@ |
||||
# This patch works around a problem with Windows RBE described in
|
||||
# https://github.com/bazelbuild/bazel/issues/11636. It can be removed
|
||||
# once that issue is resolved.
|
||||
diff --git a/go/private/rules/binary.bzl b/go/private/rules/binary.bzl
|
||||
index 40a17f4d..2741ad71 100644
|
||||
--- a/go/private/rules/binary.bzl
|
||||
+++ b/go/private/rules/binary.bzl
|
||||
@@ -462,8 +462,9 @@ exit /b %GO_EXIT_CODE%
|
||||
content = cmd,
|
||||
)
|
||||
ctx.actions.run(
|
||||
- executable = bat,
|
||||
- inputs = sdk.headers + sdk.tools + sdk.srcs + ctx.files.srcs + [sdk.go],
|
||||
+ executable = "cmd.exe",
|
||||
+ arguments = ["/S", "/C", bat.path.replace("/", "\\")],
|
||||
+ inputs = sdk.headers + sdk.tools + sdk.srcs + ctx.files.srcs + [sdk.go, bat],
|
||||
outputs = [out, gotmp],
|
||||
mnemonic = "GoToolchainBinaryBuild",
|
||||
)
|
File diff suppressed because it is too large
Load Diff
@ -1,24 +0,0 @@ |
||||
# gRPC-core BinderTransport example apps |
||||
|
||||
## Build Instruction |
||||
|
||||
1. Install Android SDK and NDK. Only NDK version >= 25 is supported. We tested against SDK Platform `33` and NDK `26.2.11394342`. |
||||
2. Make sure Bazel is at least `7.0`. Use `export OVERRIDE_BAZEL_VERSION=7.3.1` to selected a supported version listed in `bazel/supported_versions.txt` if necessary. |
||||
3. Point environment variables to install locations of SDK and NDK |
||||
``` |
||||
export ANDROID_HOME=$HOME/android-sdk |
||||
export ANDROID_NDK_HOME=$HOME/android-sdk/ndk/26.2.11394342 |
||||
``` |
||||
4. To build a fat APK that supports `x86_64`, `armv7`, and `arm64`: |
||||
``` |
||||
bazel build \ |
||||
--extra_toolchains=@androidndk//:all \ |
||||
--android_platforms=//bazel/platforms/android:x86_64,//bazel/platforms/android:armeabi-v7a,//bazel/platforms/android:arm64-v8a \ |
||||
--copt=-Wno-unknown-warning-option \ |
||||
//examples/android/binder/java/io/grpc/binder/cpp/exampleserver:app \ |
||||
//examples/android/binder/java/io/grpc/binder/cpp/exampleclient:app |
||||
``` |
||||
5. `adb install |
||||
bazel-bin/examples/android/binder/java/io/grpc/binder/cpp/exampleclient/app.apk` |
||||
6. `adb install |
||||
bazel-bin/examples/android/binder/java/io/grpc/binder/cpp/exampleserver/app.apk` |
@ -1,25 +0,0 @@ |
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android" |
||||
package="io.grpc.binder.cpp.exampleclient" |
||||
android:versionCode="1" |
||||
android:versionName="1.0" > |
||||
|
||||
<uses-sdk |
||||
android:minSdkVersion="29" |
||||
android:targetSdkVersion="30" /> |
||||
|
||||
<queries> |
||||
<package android:name="io.grpc.binder.cpp.exampleserver" /> |
||||
</queries> |
||||
|
||||
<application |
||||
android:label="gRPC BinderTransport Client Cpp"> |
||||
<activity |
||||
android:name=".MainActivity" |
||||
android:label="gRPC BinderTransport Client Cpp" > |
||||
<intent-filter> |
||||
<action android:name="android.intent.action.MAIN" /> |
||||
<category android:name="android.intent.category.LAUNCHER" /> |
||||
</intent-filter> |
||||
</activity> |
||||
</application> |
||||
</manifest> |
@ -1,51 +0,0 @@ |
||||
# 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. |
||||
|
||||
cc_library( |
||||
name = "jni_lib", |
||||
srcs = ["native.cc"], |
||||
linkopts = [ |
||||
"-ldl", |
||||
"-llog", |
||||
"-lm", |
||||
"-Wl,--no-undefined", |
||||
], |
||||
deps = [ |
||||
"//:grpc++", |
||||
"//examples/protos:helloworld_cc_grpc", |
||||
], |
||||
alwayslink = True, |
||||
) |
||||
|
||||
android_library( |
||||
name = "activity", |
||||
srcs = [ |
||||
"ButtonPressHandler.java", |
||||
"MainActivity.java", |
||||
], |
||||
manifest = "AndroidManifest.xml", |
||||
resource_files = glob(["res/**"]), |
||||
deps = [ |
||||
":jni_lib", |
||||
"@binder_transport_android_helper//io/grpc/binder/cpp:connection_helper", |
||||
], |
||||
) |
||||
|
||||
android_binary( |
||||
name = "app", |
||||
manifest = "AndroidManifest.xml", |
||||
deps = [ |
||||
":activity", |
||||
], |
||||
) |
@ -1,15 +0,0 @@ |
||||
package io.grpc.binder.cpp.exampleclient; |
||||
|
||||
import android.app.Application; |
||||
|
||||
public class ButtonPressHandler { |
||||
static { |
||||
System.loadLibrary("app"); |
||||
} |
||||
|
||||
public native String native_entry(Application application); |
||||
|
||||
public String onPressed(Application application) { |
||||
return native_entry(application); |
||||
} |
||||
} |
@ -1,26 +0,0 @@ |
||||
package io.grpc.binder.cpp.exampleclient; |
||||
|
||||
import android.app.Activity; |
||||
import android.os.Bundle; |
||||
import android.util.Log; |
||||
import android.widget.Button; |
||||
import android.widget.TextView; |
||||
|
||||
/** Main class for the example app. */ |
||||
public class MainActivity extends Activity { |
||||
@Override |
||||
public void onCreate(Bundle savedInstanceState) { |
||||
super.onCreate(savedInstanceState); |
||||
Log.v("Example", "hello, world"); |
||||
|
||||
setContentView(R.layout.activity_main); |
||||
|
||||
Button clickMeButton = findViewById(R.id.clickMeButton); |
||||
TextView exampleTextView = findViewById(R.id.exampleTextView); |
||||
|
||||
ButtonPressHandler h = new ButtonPressHandler(); |
||||
|
||||
clickMeButton.setOnClickListener( |
||||
v -> exampleTextView.setText(h.onPressed(getApplication()))); |
||||
} |
||||
} |
@ -1,73 +0,0 @@ |
||||
// 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.
|
||||
|
||||
#include <android/log.h> |
||||
#include <jni.h> |
||||
|
||||
#include "examples/protos/helloworld.grpc.pb.h" |
||||
#include "examples/protos/helloworld.pb.h" |
||||
|
||||
#include <grpcpp/create_channel_binder.h> |
||||
#include <grpcpp/security/binder_security_policy.h> |
||||
|
||||
extern "C" JNIEXPORT jstring JNICALL |
||||
Java_io_grpc_binder_cpp_exampleclient_ButtonPressHandler_native_1entry( |
||||
JNIEnv* env, jobject /*this*/, jobject application) { |
||||
// Lower the gRPC logging level, here it is just for demo and debugging
|
||||
// purpose.
|
||||
setenv("GRPC_VERBOSITY", "INFO", true); |
||||
if (grpc::experimental::InitializeBinderChannelJavaClass(env)) { |
||||
__android_log_print(ANDROID_LOG_INFO, "DemoClient", |
||||
"InitializeBinderChannelJavaClass succeed"); |
||||
} else { |
||||
__android_log_print(ANDROID_LOG_INFO, "DemoClient", |
||||
"InitializeBinderChannelJavaClass failed"); |
||||
} |
||||
static bool first = true; |
||||
static std::shared_ptr<grpc::Channel> channel; |
||||
if (first) { |
||||
first = false; |
||||
JavaVM* jvm; |
||||
{ |
||||
jint result = env->GetJavaVM(&jvm); |
||||
assert(result == 0); |
||||
} |
||||
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), |
||||
ch_args); |
||||
return env->NewStringUTF("Clicked 1 time, channel created"); |
||||
} else { |
||||
auto stub = helloworld::Greeter::NewStub(channel); |
||||
grpc::ClientContext context; |
||||
helloworld::HelloRequest request; |
||||
helloworld::HelloReply response; |
||||
request.set_name("BinderTransportClient"); |
||||
grpc::Status status = stub->SayHello(&context, request, &response); |
||||
if (status.ok()) { |
||||
return env->NewStringUTF(response.message().c_str()); |
||||
} |
||||
return env->NewStringUTF( |
||||
std::string("Clicked more than 1 time. Status not ok " + |
||||
std::to_string(status.error_code())) |
||||
.c_str()); |
||||
} |
||||
} |
@ -1,24 +0,0 @@ |
||||
<?xml version="1.0" encoding="utf-8"?> |
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" |
||||
android:padding="16dp" |
||||
android:orientation="vertical" |
||||
android:gravity="center_vertical" |
||||
android:layout_width="match_parent" |
||||
android:layout_height="match_parent"> |
||||
|
||||
<TextView |
||||
android:id="@+id/exampleTextView" |
||||
android:layout_width="wrap_content" |
||||
android:layout_height="wrap_content" |
||||
android:layout_gravity="center_horizontal" |
||||
android:textSize="32dp" |
||||
android:text="@string/thinking_face"/> |
||||
|
||||
<Button |
||||
android:id="@+id/clickMeButton" |
||||
android:layout_width="wrap_content" |
||||
android:layout_height="wrap_content" |
||||
android:layout_gravity="center_horizontal" |
||||
android:layout_marginTop="16dp" |
||||
android:text="@string/click_me_button"/> |
||||
</LinearLayout> |
@ -1,5 +0,0 @@ |
||||
<?xml version="1.0" encoding="utf-8"?> |
||||
<resources> |
||||
<string name="click_me_button">Run example</string> |
||||
<string name="thinking_face">🤔</string> |
||||
</resources> |
@ -1,21 +0,0 @@ |
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android" |
||||
package="io.grpc.binder.cpp.exampleserver" |
||||
android:versionCode="1" |
||||
android:versionName="1.0" > |
||||
|
||||
<uses-sdk |
||||
android:minSdkVersion="29" |
||||
android:targetSdkVersion="30" /> |
||||
|
||||
<application |
||||
android:label="gRPC BinderTransport Server Cpp"> |
||||
<activity |
||||
android:name=".MainActivity" |
||||
android:label="gRPC BinderTransport Server Cpp" > |
||||
<intent-filter> |
||||
<action android:name="android.intent.action.MAIN" /> |
||||
<category android:name="android.intent.category.LAUNCHER" /> |
||||
</intent-filter> |
||||
</activity> |
||||
</application> |
||||
</manifest> |
@ -1,10 +0,0 @@ |
||||
<?xml version="1.0" encoding="utf-8"?> |
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android" |
||||
package="io.grpc.binder.cpp.exampleserver"> |
||||
<uses-sdk android:minSdkVersion="29" android:targetSdkVersion="30"/> |
||||
<application> |
||||
<service |
||||
android:name=".ExportedEndpointService" |
||||
android:exported="true"/> |
||||
</application> |
||||
</manifest> |
@ -1,61 +0,0 @@ |
||||
# 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. |
||||
|
||||
cc_library( |
||||
name = "jni_lib", |
||||
srcs = ["native.cc"], |
||||
linkopts = [ |
||||
"-ldl", |
||||
"-llog", |
||||
"-lm", |
||||
"-Wl,--no-undefined", |
||||
], |
||||
deps = [ |
||||
"//:grpc++", |
||||
"//examples/protos:helloworld_cc_grpc", |
||||
], |
||||
alwayslink = True, |
||||
) |
||||
|
||||
android_library( |
||||
name = "activity", |
||||
srcs = [ |
||||
"ButtonPressHandler.java", |
||||
"MainActivity.java", |
||||
], |
||||
manifest = "AndroidManifest.xml", |
||||
resource_files = glob(["res/**"]), |
||||
deps = [ |
||||
":endpoint", |
||||
":jni_lib", |
||||
], |
||||
) |
||||
|
||||
android_library( |
||||
name = "endpoint", |
||||
srcs = ["ExportedEndpointService.java"], |
||||
exports_manifest = True, |
||||
manifest = "AndroidManifest_endpoint.xml", |
||||
deps = [ |
||||
"@binder_transport_android_helper//io/grpc/binder/cpp:connection_helper", |
||||
], |
||||
) |
||||
|
||||
android_binary( |
||||
name = "app", |
||||
manifest = "AndroidManifest.xml", |
||||
deps = [ |
||||
":activity", |
||||
], |
||||
) |
@ -1,13 +0,0 @@ |
||||
package io.grpc.binder.cpp.exampleserver; |
||||
|
||||
import android.app.Application; |
||||
|
||||
public class ButtonPressHandler { |
||||
static { |
||||
System.loadLibrary("app"); |
||||
} |
||||
|
||||
public String onPressed(Application application) { |
||||
return "Server Button Pressed"; |
||||
} |
||||
} |
@ -1,26 +0,0 @@ |
||||
package io.grpc.binder.cpp.exampleserver; |
||||
|
||||
import android.app.Service; |
||||
import android.content.Intent; |
||||
import android.os.IBinder; |
||||
import android.content.Context; |
||||
import io.grpc.binder.cpp.GrpcCppServerBuilder; |
||||
|
||||
/** Exposes gRPC services running in the main process */ |
||||
public final class ExportedEndpointService extends Service { |
||||
static { |
||||
System.loadLibrary("app"); |
||||
} |
||||
|
||||
public ExportedEndpointService() { |
||||
init_grpc_server(this); |
||||
} |
||||
|
||||
@Override |
||||
public IBinder onBind(Intent intent) { |
||||
// The argument should match the URI passed into grpc::ServerBuilder::AddListeningPort
|
||||
return GrpcCppServerBuilder.GetEndpointBinder("binder:example.service"); |
||||
} |
||||
|
||||
public native void init_grpc_server(Context context); |
||||
} |
@ -1,27 +0,0 @@ |
||||
package io.grpc.binder.cpp.exampleserver; |
||||
|
||||
import android.app.Activity; |
||||
import android.os.Bundle; |
||||
import android.util.Log; |
||||
import android.widget.Button; |
||||
import android.widget.TextView; |
||||
import io.grpc.binder.cpp.exampleserver.R; |
||||
|
||||
/** Main class for the example app. */ |
||||
public class MainActivity extends Activity { |
||||
@Override |
||||
public void onCreate(Bundle savedInstanceState) { |
||||
super.onCreate(savedInstanceState); |
||||
Log.v("Example", "hello, world"); |
||||
|
||||
setContentView(R.layout.activity_main); |
||||
|
||||
Button clickMeButton = findViewById(R.id.clickMeButton); |
||||
TextView exampleTextView = findViewById(R.id.exampleTextView); |
||||
|
||||
ButtonPressHandler h = new ButtonPressHandler(); |
||||
|
||||
clickMeButton.setOnClickListener( |
||||
v -> exampleTextView.setText(h.onPressed(getApplication()))); |
||||
} |
||||
} |
@ -1,83 +0,0 @@ |
||||
// 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.
|
||||
|
||||
#include <android/log.h> |
||||
#include <jni.h> |
||||
|
||||
#include "examples/protos/helloworld.grpc.pb.h" |
||||
#include "examples/protos/helloworld.pb.h" |
||||
|
||||
#include <grpcpp/create_channel_binder.h> |
||||
#include <grpcpp/grpcpp.h> |
||||
#include <grpcpp/security/binder_credentials.h> |
||||
#include <grpcpp/security/binder_security_policy.h> |
||||
|
||||
namespace { |
||||
class GreeterService : public helloworld::Greeter::Service { |
||||
public: |
||||
grpc::Status SayHello(grpc::ServerContext*, |
||||
const helloworld::HelloRequest* request, |
||||
helloworld::HelloReply* response) override { |
||||
__android_log_print(ANDROID_LOG_INFO, "DemoServer", "Line number %d", |
||||
__LINE__); |
||||
__android_log_print(ANDROID_LOG_INFO, "DemoServer", "Got hello request: %s", |
||||
request->name().c_str()); |
||||
response->set_message("Hi, " + request->name()); |
||||
return grpc::Status::OK; |
||||
} |
||||
}; |
||||
|
||||
} // namespace
|
||||
|
||||
extern "C" JNIEXPORT void JNICALL |
||||
Java_io_grpc_binder_cpp_exampleserver_ExportedEndpointService_init_1grpc_1server( |
||||
JNIEnv* env, jobject /*this*/, jobject context) { |
||||
// Lower the gRPC logging level, here it is just for demo and debugging
|
||||
// purpose.
|
||||
setenv("GRPC_VERBOSITY", "INFO", true); |
||||
__android_log_print(ANDROID_LOG_INFO, "DemoServer", "Line number %d", |
||||
__LINE__); |
||||
static std::unique_ptr<grpc::Server> server = nullptr; |
||||
|
||||
if (server != nullptr) { |
||||
// Already initiated
|
||||
return; |
||||
} |
||||
|
||||
if (grpc::experimental::InitializeBinderChannelJavaClass(env)) { |
||||
__android_log_print(ANDROID_LOG_INFO, "DemoServer", |
||||
"InitializeBinderChannelJavaClass succeed"); |
||||
} else { |
||||
__android_log_print(ANDROID_LOG_INFO, "DemoServer", |
||||
"InitializeBinderChannelJavaClass failed"); |
||||
} |
||||
|
||||
static GreeterService service; |
||||
grpc::ServerBuilder server_builder; |
||||
server_builder.RegisterService(&service); |
||||
|
||||
JavaVM* jvm; |
||||
{ |
||||
jint result = env->GetJavaVM(&jvm); |
||||
assert(result == 0); |
||||
} |
||||
server_builder.AddListeningPort( |
||||
"binder:example.service", |
||||
grpc::experimental::BinderServerCredentials( |
||||
std::make_shared< |
||||
grpc::experimental::binder::SameSignatureSecurityPolicy>( |
||||
jvm, context))); |
||||
|
||||
server = server_builder.BuildAndStart(); |
||||
} |
@ -1,24 +0,0 @@ |
||||
<?xml version="1.0" encoding="utf-8"?> |
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" |
||||
android:padding="16dp" |
||||
android:orientation="vertical" |
||||
android:gravity="center_vertical" |
||||
android:layout_width="match_parent" |
||||
android:layout_height="match_parent"> |
||||
|
||||
<TextView |
||||
android:id="@+id/exampleTextView" |
||||
android:layout_width="wrap_content" |
||||
android:layout_height="wrap_content" |
||||
android:layout_gravity="center_horizontal" |
||||
android:textSize="32dp" |
||||
android:text="@string/thinking_face"/> |
||||
|
||||
<Button |
||||
android:id="@+id/clickMeButton" |
||||
android:layout_width="wrap_content" |
||||
android:layout_height="wrap_content" |
||||
android:layout_gravity="center_horizontal" |
||||
android:layout_marginTop="16dp" |
||||
android:text="@string/click_me_button"/> |
||||
</LinearLayout> |
@ -1,5 +0,0 @@ |
||||
<?xml version="1.0" encoding="utf-8"?> |
||||
<resources> |
||||
<string name="click_me_button">Run example</string> |
||||
<string name="thinking_face">🤔</string> |
||||
</resources> |
@ -0,0 +1,126 @@ |
||||
/*
|
||||
* |
||||
* Copyright 2024 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. |
||||
* |
||||
*/ |
||||
|
||||
#include <grpc/grpc.h> |
||||
#include <grpcpp/ext/proto_server_reflection_plugin.h> |
||||
#include <grpcpp/grpcpp.h> |
||||
|
||||
#include <cstddef> |
||||
#include <ostream> |
||||
#include <string> |
||||
|
||||
#include "absl/flags/flag.h" |
||||
#include "absl/flags/parse.h" |
||||
|
||||
#ifdef BAZEL_BUILD |
||||
#include "examples/protos/helloworld.grpc.pb.h" |
||||
#else |
||||
#include "helloworld.grpc.pb.h" |
||||
#endif |
||||
|
||||
ABSL_FLAG(std::string, target, "localhost:50051", "Server address"); |
||||
|
||||
using grpc::CallbackServerContext; |
||||
using grpc::Channel; |
||||
using grpc::ClientContext; |
||||
using grpc::Server; |
||||
using grpc::ServerBuilder; |
||||
using grpc::ServerUnaryReactor; |
||||
using grpc::Status; |
||||
using helloworld::Greeter; |
||||
using helloworld::HelloReply; |
||||
using helloworld::HelloRequest; |
||||
|
||||
namespace { |
||||
|
||||
// Sends requests as quickly as possible and times how long it takes to perform
|
||||
// the write operation.
|
||||
class GreeterClientReactor final |
||||
: public grpc::ClientBidiReactor<helloworld::HelloRequest, |
||||
helloworld::HelloReply> { |
||||
public: |
||||
explicit GreeterClientReactor(int reqs, size_t req_size) : reqs_(reqs) { |
||||
req_.set_name(std::string(req_size, '*')); |
||||
} |
||||
|
||||
void Start() { |
||||
absl::MutexLock lock(&mu_); |
||||
StartCall(); |
||||
Write(); |
||||
} |
||||
|
||||
~GreeterClientReactor() override { |
||||
absl::MutexLock lock(&mu_); |
||||
mu_.Await(absl::Condition(+[](bool* done) { return *done; }, &done_)); |
||||
} |
||||
|
||||
void OnWriteDone(bool ok) override { |
||||
absl::MutexLock lock(&mu_); |
||||
std::cout << "Writing took " << absl::Now() - *time_ << std::endl; |
||||
time_ = absl::nullopt; |
||||
if (ok) { |
||||
Write(); |
||||
} |
||||
} |
||||
|
||||
void OnDone(const grpc::Status& status) override { |
||||
if (status.ok()) { |
||||
std::cout << "Done\n"; |
||||
} else { |
||||
std::cout << "Done with error: [" << status.error_code() << "] " |
||||
<< status.error_message() << "\n"; |
||||
} |
||||
absl::MutexLock lock(&mu_); |
||||
done_ = true; |
||||
} |
||||
|
||||
private: |
||||
void Write() ABSL_EXCLUSIVE_LOCKS_REQUIRED(&mu_) { |
||||
if (reqs_ == 0) { |
||||
StartWritesDone(); |
||||
return; |
||||
} |
||||
--reqs_; |
||||
StartWrite(&req_); |
||||
time_ = absl::Now(); |
||||
} |
||||
|
||||
absl::Mutex mu_; |
||||
bool done_ ABSL_GUARDED_BY(&mu_) = false; |
||||
HelloRequest req_; |
||||
size_t reqs_; |
||||
absl::optional<absl::Time> time_ ABSL_GUARDED_BY(mu_); |
||||
}; |
||||
|
||||
} // namespace
|
||||
|
||||
int main(int argc, char** argv) { |
||||
absl::ParseCommandLine(argc, argv); |
||||
grpc::ChannelArguments channel_arguments; |
||||
auto channel = grpc::CreateCustomChannel(absl::GetFlag(FLAGS_target), |
||||
grpc::InsecureChannelCredentials(), |
||||
channel_arguments); |
||||
auto stub = Greeter::NewStub(channel); |
||||
// Send 10 requests with 3Mb payload. This will eventually fill the buffer
|
||||
// and make
|
||||
GreeterClientReactor reactor(10, 3 * 1024 * 1024); |
||||
grpc::ClientContext context; |
||||
stub->async()->SayHelloBidiStream(&context, &reactor); |
||||
reactor.Start(); |
||||
return 0; |
||||
} |
@ -0,0 +1,111 @@ |
||||
/*
|
||||
* |
||||
* 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. |
||||
* |
||||
*/ |
||||
|
||||
#include <grpcpp/ext/proto_server_reflection_plugin.h> |
||||
#include <grpcpp/grpcpp.h> |
||||
#include <grpcpp/health_check_service_interface.h> |
||||
|
||||
#include <cstddef> |
||||
#include <cstdint> |
||||
#include <iostream> |
||||
#include <string> |
||||
|
||||
#include "absl/flags/flag.h" |
||||
#include "absl/flags/parse.h" |
||||
#include "absl/strings/str_format.h" |
||||
|
||||
#ifdef BAZEL_BUILD |
||||
#include "examples/protos/helloworld.grpc.pb.h" |
||||
#else |
||||
#include "helloworld.grpc.pb.h" |
||||
#endif |
||||
|
||||
ABSL_FLAG(uint16_t, port, 50051, "Server port for the service"); |
||||
ABSL_FLAG(size_t, quota, 20, "Resource quota, in megabytes"); |
||||
|
||||
namespace { |
||||
|
||||
//
|
||||
// Server reactor that is slow to read incoming messages, causing the buffers
|
||||
// to fill.
|
||||
//
|
||||
class SlowReadingBidiReactor final |
||||
: public grpc::ServerBidiReactor<helloworld::HelloRequest, |
||||
helloworld::HelloReply> { |
||||
public: |
||||
SlowReadingBidiReactor() { StartRead(&req_); } |
||||
|
||||
void OnReadDone(bool ok) override { |
||||
std::cout << "Recieved request with " << req_.name().length() |
||||
<< " bytes name\n"; |
||||
if (!ok) { |
||||
Finish(grpc::Status::OK); |
||||
return; |
||||
} |
||||
sleep(1); |
||||
StartRead(&req_); |
||||
} |
||||
|
||||
void OnDone() override { |
||||
std::cout << "Done\n"; |
||||
delete this; |
||||
} |
||||
|
||||
private: |
||||
absl::Mutex mu_; |
||||
helloworld::HelloRequest req_; |
||||
}; |
||||
|
||||
// Logic and data behind the server's behavior.
|
||||
class GreeterServiceImpl final : public helloworld::Greeter::CallbackService { |
||||
grpc::ServerBidiReactor<helloworld::HelloRequest, helloworld::HelloReply>* |
||||
SayHelloBidiStream(grpc::CallbackServerContext* /* context */) override { |
||||
return new SlowReadingBidiReactor(); |
||||
} |
||||
}; |
||||
|
||||
} // namespace
|
||||
|
||||
void RunServer(uint16_t port) { |
||||
std::string server_address = absl::StrFormat("0.0.0.0:%d", port); |
||||
GreeterServiceImpl service; |
||||
|
||||
grpc::EnableDefaultHealthCheckService(true); |
||||
grpc::reflection::InitProtoReflectionServerBuilderPlugin(); |
||||
grpc::ServerBuilder builder; |
||||
// Listen on the given address without any authentication mechanism.
|
||||
builder.AddListeningPort(server_address, grpc::InsecureServerCredentials()); |
||||
// Register "service" as the instance through which we'll communicate with
|
||||
// clients. In this case it corresponds to an *synchronous* service.
|
||||
builder.RegisterService(&service); |
||||
grpc::ResourceQuota quota; |
||||
quota.Resize(absl::GetFlag(FLAGS_quota) * 1024 * 1024); |
||||
// Finally assemble the server.
|
||||
auto server = builder.BuildAndStart(); |
||||
std::cout << "Server listening on " << server_address << std::endl; |
||||
|
||||
// Wait for the server to shutdown. Note that some other thread must be
|
||||
// responsible for shutting down the server for this call to ever return.
|
||||
server->Wait(); |
||||
} |
||||
|
||||
int main(int argc, char** argv) { |
||||
absl::ParseCommandLine(argc, argv); |
||||
RunServer(absl::GetFlag(FLAGS_port)); |
||||
return 0; |
||||
} |
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in new issue