1 // Copyright 2021 gRPC authors.
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14
15 #include <grpc/support/port_platform.h>
16
17 #ifndef GRPC_NO_BINDER
18
19 #include <grpcpp/create_channel_binder.h>
20
21 // The interface is only defined if GPR_ANDROID is defined, because some
22 // arguments requires JNI.
23 // Furthermore, the interface is non-phony only when
24 // GPR_SUPPORT_BINDER_TRANSPORT is true because actual implementation of binder
25 // transport requires newer version of NDK API
26
27 #ifdef GPR_ANDROID
28
29 #include <grpc/grpc.h>
30 #include <grpc/grpc_posix.h>
31 #include <grpc/support/log.h>
32
33 #include "src/core/lib/gprpp/crash.h"
34
35 #ifdef GPR_SUPPORT_BINDER_TRANSPORT
36
37 #include <grpc/support/port_platform.h>
38
39 #include "absl/memory/memory.h"
40 #include "absl/strings/substitute.h"
41 #include "absl/time/clock.h"
42 #include "absl/time/time.h"
43
44 #include <grpcpp/impl/grpc_library.h>
45
46 #include "src/core/ext/filters/client_channel/client_channel.h"
47 #include "src/core/ext/transport/binder/client/channel_create_impl.h"
48 #include "src/core/ext/transport/binder/client/connection_id_generator.h"
49 #include "src/core/ext/transport/binder/client/endpoint_binder_pool.h"
50 #include "src/core/ext/transport/binder/client/jni_utils.h"
51 #include "src/core/ext/transport/binder/client/security_policy_setting.h"
52 #include "src/core/ext/transport/binder/transport/binder_transport.h"
53 #include "src/core/ext/transport/binder/wire_format/binder.h"
54 #include "src/core/ext/transport/binder/wire_format/binder_android.h"
55 #include "src/core/lib/channel/channel_args.h"
56 #include "src/core/lib/config/core_configuration.h"
57 #include "src/core/lib/surface/channel.h"
58 #include "src/core/lib/transport/transport.h"
59 #include "src/cpp/client/create_channel_internal.h"
60
61 namespace {
62 // grpc.io.action.BIND is the standard action name for binding to binder
63 // transport server.
64 const char* kStandardActionName = "grpc.io.action.BIND";
65 } // namespace
66
67 namespace grpc {
68 namespace experimental {
69
CreateBinderChannel(void * jni_env_void,jobject context,absl::string_view package_name,absl::string_view class_name,std::shared_ptr<grpc::experimental::binder::SecurityPolicy> security_policy)70 std::shared_ptr<grpc::Channel> CreateBinderChannel(
71 void* jni_env_void, jobject context, absl::string_view package_name,
72 absl::string_view class_name,
73 std::shared_ptr<grpc::experimental::binder::SecurityPolicy>
74 security_policy) {
75 return CreateCustomBinderChannel(jni_env_void, context, package_name,
76 class_name, security_policy,
77 ChannelArguments());
78 }
79
CreateCustomBinderChannel(void * jni_env_void,jobject context,absl::string_view package_name,absl::string_view class_name,std::shared_ptr<grpc::experimental::binder::SecurityPolicy> security_policy,const ChannelArguments & args)80 std::shared_ptr<grpc::Channel> CreateCustomBinderChannel(
81 void* jni_env_void, jobject context, absl::string_view package_name,
82 absl::string_view class_name,
83 std::shared_ptr<grpc::experimental::binder::SecurityPolicy> security_policy,
84 const ChannelArguments& args) {
85 return CreateCustomBinderChannel(
86 jni_env_void, context,
87 absl::Substitute("android-app://$0#Intent;action=$1;component=$0/$2;end",
88 package_name, kStandardActionName, class_name),
89 security_policy, args);
90 }
91
CreateBinderChannel(void * jni_env_void,jobject context,absl::string_view uri,std::shared_ptr<grpc::experimental::binder::SecurityPolicy> security_policy)92 std::shared_ptr<grpc::Channel> CreateBinderChannel(
93 void* jni_env_void, jobject context, absl::string_view uri,
94 std::shared_ptr<grpc::experimental::binder::SecurityPolicy>
95 security_policy) {
96 return CreateCustomBinderChannel(jni_env_void, context, uri, security_policy,
97 ChannelArguments());
98 }
99
CreateCustomBinderChannel(void * jni_env_void,jobject context,absl::string_view uri,std::shared_ptr<grpc::experimental::binder::SecurityPolicy> security_policy,const ChannelArguments & args)100 std::shared_ptr<grpc::Channel> CreateCustomBinderChannel(
101 void* jni_env_void, jobject context, absl::string_view uri,
102 std::shared_ptr<grpc::experimental::binder::SecurityPolicy> security_policy,
103 const ChannelArguments& args) {
104 grpc_init();
105
106 GPR_ASSERT(jni_env_void != nullptr);
107 GPR_ASSERT(security_policy != nullptr);
108
109 // Generate an unique connection ID that identifies this connection (Useful
110 // for mapping connection between Java and C++ code).
111 std::string connection_id =
112 grpc_binder::GetConnectionIdGenerator()->Generate(uri);
113
114 gpr_log(GPR_ERROR, "connection id is %s", connection_id.c_str());
115
116 // After invoking this Java method, Java code will put endpoint binder into
117 // `EndpointBinderPool` after the connection succeeds
118 // TODO(mingcl): Consider if we want to delay the connection establishment
119 // until SubchannelConnector start establishing connection. For now we don't
120 // see any benifits doing that.
121 grpc_binder::TryEstablishConnectionWithUri(static_cast<JNIEnv*>(jni_env_void),
122 context, uri, connection_id);
123
124 grpc_channel_args channel_args;
125 args.SetChannelArgs(&channel_args);
126
127 // Set server URI to a URI that contains connection id. The URI will be used
128 // by subchannel connector to obtain correct endpoint binder from
129 // `EndpointBinderPool`.
130 grpc_channel_args* new_args;
131 {
132 string server_uri = "binder:" + connection_id;
133 grpc_arg server_uri_arg =
134 grpc_channel_arg_string_create(const_cast<char*>(GRPC_ARG_SERVER_URI),
135 const_cast<char*>(server_uri.c_str()));
136 const char* to_remove[] = {GRPC_ARG_SERVER_URI};
137 new_args = grpc_channel_args_copy_and_add_and_remove(
138 &channel_args, to_remove, 1, &server_uri_arg, 1);
139 }
140
141 grpc_binder::GetSecurityPolicySetting()->Set(connection_id, security_policy);
142
143 auto channel = CreateChannelInternal(
144 "", grpc::internal::CreateClientBinderChannelImpl(new_args),
145 std::vector<
146 std::unique_ptr<experimental::ClientInterceptorFactoryInterface>>());
147
148 grpc_channel_args_destroy(new_args);
149
150 return channel;
151 }
152
InitializeBinderChannelJavaClass(void * jni_env_void)153 bool InitializeBinderChannelJavaClass(void* jni_env_void) {
154 return grpc_binder::FindNativeConnectionHelper(
155 static_cast<JNIEnv*>(jni_env_void)) != nullptr;
156 }
157
InitializeBinderChannelJavaClass(void * jni_env_void,std::function<void * (std::string)> class_finder)158 bool InitializeBinderChannelJavaClass(
159 void* jni_env_void, std::function<void*(std::string)> class_finder) {
160 return grpc_binder::FindNativeConnectionHelper(
161 static_cast<JNIEnv*>(jni_env_void), class_finder) != nullptr;
162 }
163
164 } // namespace experimental
165 } // namespace grpc
166
167 #else // !GPR_SUPPORT_BINDER_TRANSPORT
168
169 namespace grpc {
170 namespace experimental {
171
CreateBinderChannel(void *,jobject,absl::string_view,absl::string_view,std::shared_ptr<grpc::experimental::binder::SecurityPolicy>)172 std::shared_ptr<grpc::Channel> CreateBinderChannel(
173 void*, jobject, absl::string_view, absl::string_view,
174 std::shared_ptr<grpc::experimental::binder::SecurityPolicy>) {
175 gpr_log(GPR_ERROR,
176 "This APK is compiled with Android API level = %d, which is not "
177 "supported. See port_platform.h for supported versions.",
178 __ANDROID_API__);
179 GPR_ASSERT(0);
180 return {};
181 }
182
CreateCustomBinderChannel(void *,jobject,absl::string_view,absl::string_view,std::shared_ptr<grpc::experimental::binder::SecurityPolicy>,const ChannelArguments &)183 std::shared_ptr<grpc::Channel> CreateCustomBinderChannel(
184 void*, jobject, absl::string_view, absl::string_view,
185 std::shared_ptr<grpc::experimental::binder::SecurityPolicy>,
186 const ChannelArguments&) {
187 gpr_log(GPR_ERROR,
188 "This APK is compiled with Android API level = %d, which is not "
189 "supported. See port_platform.h for supported versions.",
190 __ANDROID_API__);
191 GPR_ASSERT(0);
192 return {};
193 }
194
CreateBinderChannel(void *,jobject,absl::string_view,std::shared_ptr<grpc::experimental::binder::SecurityPolicy>)195 std::shared_ptr<grpc::Channel> CreateBinderChannel(
196 void*, jobject, absl::string_view,
197 std::shared_ptr<grpc::experimental::binder::SecurityPolicy>) {
198 gpr_log(GPR_ERROR,
199 "This APK is compiled with Android API level = %d, which is not "
200 "supported. See port_platform.h for supported versions.",
201 __ANDROID_API__);
202 GPR_ASSERT(0);
203 return {};
204 }
205
CreateCustomBinderChannel(void *,jobject,absl::string_view,std::shared_ptr<grpc::experimental::binder::SecurityPolicy>,const ChannelArguments &)206 std::shared_ptr<grpc::Channel> CreateCustomBinderChannel(
207 void*, jobject, absl::string_view,
208 std::shared_ptr<grpc::experimental::binder::SecurityPolicy>,
209 const ChannelArguments&) {
210 gpr_log(GPR_ERROR,
211 "This APK is compiled with Android API level = %d, which is not "
212 "supported. See port_platform.h for supported versions.",
213 __ANDROID_API__);
214 GPR_ASSERT(0);
215 return {};
216 }
217
InitializeBinderChannelJavaClass(void * jni_env_void)218 bool InitializeBinderChannelJavaClass(void* jni_env_void) {
219 gpr_log(GPR_ERROR,
220 "This APK is compiled with Android API level = %d, which is not "
221 "supported. See port_platform.h for supported versions.",
222 __ANDROID_API__);
223 GPR_ASSERT(0);
224 return {};
225 }
226
InitializeBinderChannelJavaClass(void * jni_env_void,std::function<void * (std::string)> class_finder)227 bool InitializeBinderChannelJavaClass(
228 void* jni_env_void, std::function<void*(std::string)> class_finder) {
229 gpr_log(GPR_ERROR,
230 "This APK is compiled with Android API level = %d, which is not "
231 "supported. See port_platform.h for supported versions.",
232 __ANDROID_API__);
233 GPR_ASSERT(0);
234 return {};
235 }
236
237 } // namespace experimental
238 } // namespace grpc
239
240 #endif // GPR_SUPPORT_BINDER_TRANSPORT
241
242 #endif // GPR_ANDROID
243
244 #endif // GRPC_NO_BINDER
245